Как из UIView открыть UIViewController, а потом закрыть


#1

Здравтвуйте.
Пытаюсь из UIView открыть UIViewControlle следуюющим образом

class PlayerDetailsView: UIView

@IBAction func userProfileButton(_ sender: UIButton) {
            print("Go to Profile!")
            let mainTabBarController =  UIApplication.shared.keyWindow?.rootViewController as? MainTabBarController
            mainTabBarController?.minimizePlayerDetails(record: nil)

            let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)

            let userProfileController = storyBoard.instantiateViewController(withIdentifier: "ProfileViewController") as! ProfileViewController

            userProfileController.userId = record?.userUid
            
            var topVC = UIApplication.shared.keyWindow?.rootViewController
               while((topVC!.presentedViewController) != nil) {
                   topVC = topVC!.presentedViewController
               }
    
               let navController = UINavigationController(rootViewController: userProfileController)
               navController.modalPresentationStyle = .pageSheet

               topVC?.present(navController, animated: true, completion: nil)
    }

и все работает. Но вот закрыть открытый UIViewController невозможно, нет кнопки Назад (как в при обычном UINavigationController). Возможно только свернуть, если применить свойство navController.modalPresentationStyle = .pageSheet, но это в свою очередь работает на новых девайсах и iOS 13 и выше, а старых девайсах и iOS10 и 11 (может и 12, не проверял) не такой опции и UIViewController занимает весь экран без всякой возможности его свернуть или вернуться. Как можно это побороть?


#2

Кнопка назад по у молчанию появляется в навигационном стеке с второго экрана, что логично, вы же презентуете стек с один экраном, ее там не будте)
Можете добавить в навигационный бар свой бар итем, по нажатию на который делать dissmiss, либо вызывать dissmiss из презентованного экрана


#3

@Jack Да, спасибо. Переспал с этой проблемой ночь и тоже дошел до того, что кнопка назад не может появиться на первом View))). Другой вопрос: UIViewController, который я открываю задействован еще и в других сценариях работы приложения и там кнопка dissmiss не нужна. можно ли как-то сделать, чтобы она появлялась конкретно только после перехода из View и пропадала после реализации и нигде больше по ходу работы приложения не появлялась? Если можно, то как?


#4

Добавьте свойство в ProfileController var showBackButton: Bool = false
перед показом VC меняйте это свойство когда нужно

let userProfileController = storyBoard.instantiateViewController(withIdentifier: "ProfileViewController") as! ProfileViewController
userProfileController.showBackButton = true

А уже в самом VC проверяйте свойство и делайте что нужно.


#5
class View: UIView {
    
    private var dissmissNC: (() -> Void)?
    
    func getTopViewController() -> UIViewController? {
        // YOUR CODE
        return nil
    }
    
    @objc func handleButtonTap(_ sender: UIControl) {
        let vc = UIViewController()
        let nc = UINavigationController(rootViewController: vc)
        let item = UIBarButtonItem(barButtonSystemItem: .close, target: self, action: #selector(handleNavigationCloseItemTap(_:)))
        item.title = "close"
        vc.navigationItem.rightBarButtonItem = item
        
        guard let topVC = getTopViewController() else {
            preconditionFailure("Error get top vc")
        }
        topVC.present(nc, animated: true, completion: nil)
        
        dissmissNC = { [weak nc] in nc?.dismiss(animated: true, completion: nil) }
    }
    
    @objc func handleNavigationCloseItemTap(_ sender: UINavigationItem) {
        dissmissNC?()
    }
}

Или что-то по типу такого)


#6

@RexHunt Спасибо, все получилось


#7

@Jack Спасибо, все получилось. Ваш вариант тоже рабочий