@Raserad
Начинающий разработчик сайтов и приложений

Как заставить работать swipe gesture в uinavigationcontroller?

Здравствуйте. Следующая проблема. Я программно добавляю в приложение uinavigationcontroller как rootviewcontroller. В нем скрываю navigationBar с помощью setNavigationBarHidden(true). К сожалению swipe жест назад не работает. Тупо не реагирует на swipe. Перепробовал все что на stackoverflow. Даже либу использовал - бестолку. Уже не знаю где и искать решение

Код инициализации router

private var window: UIWindow
    
    private var rootNavigationController: UINavigationController!
    
    init( _ window: UIWindow) {
        self.window = window
        self.initNavigation()
    }
    
    private func initNavigation() {
        rootNavigationController = UINavigationController()
        rootNavigationController.setNavigationBarHidden(true, animated: false)
        window.rootViewController = rootNavigationController
        window.makeKeyAndVisible()
        window.backgroundColor = .white
    }


Код вставки нового viewcontroller:
private func goBackToViewController(_ navigation: UINavigationController, _ viewController: UIViewController) -> Bool {
        for controller in navigation.viewControllers {
            if controller.isKind(of: type(of: viewController)) {
                navigation.popToViewController(controller, animated: true)
                return true
            }
        }
        
        return false
    }

       private func showViewControllerByMethod(_ navigation: UINavigationController, _ viewController: UIViewController, _ method: ViewControllerShowMethod) {
        switch(method) {
        case .normal:
            navigation.pushViewController(viewController, animated: true)
        case .modal:
            navigation.present(viewController, animated: true)
        }
    }

     private func show(navigation: UINavigationController, _ viewController: UIViewController, method: PageShowMethod) {
        DispatchQueue.main.async {
            if(self.goBackToViewController(navigation, viewController)) {
                return
            }
            
            navigation.view.endEditing(true)
            
            self.showViewControllerByMethod(navigation, viewController, method)
        }
    }


Код получения viewcontroller из любого storiboard в проекте

private func getController(storyboard storyboardName: String, controllerName: String? = nil) -> UIViewController? {
        
        let storyboard = UIStoryboard(name: storyboardName, bundle: nil)
        
        let controller = controllerName == nil ?
            storyboard.instantiateInitialViewController() :
            storyboard.instantiateViewController(withIdentifier: controllerName!)
        
        return controller
    }


И наконец код инициализации первого rootviewcontroller в uinavigationcontroller:

func showFirstViewController() {
        var viewControllers = [UIViewController]()
        
        let firstTabController = getController(storyboard: "First") as! FirstViewController
        let firstTabNavigation = UINavigationController(rootViewController: firstTabController)
        firstTabNavigation.setNavigationBarHidden(true, animated: false)
        firstTabNavigation.tabBarItem = UITabBarItem(title: nil, image: UIImage(named: "home-icon"), selectedImage: UIImage(named: "home-filled-icon"))
        viewControllers.append(firstTabNavigation)
        
        let secondTabController = getController(storyboard: "Second") as! SecondViewController
        let secondTabNavigation = UINavigationController(rootViewController: secondTabController)
        secondTabNavigation.tabBarItem = UITabBarItem(title: nil, image: UIImage(named: "second-icon"), selectedImage: UIImage(named: "second-filled-icon"))
        viewControllers.append(secondTabNavigation)
        
        let tabBarController = BasicTabContainerViewController()
        tabBarController.viewControllers = viewControllers
        
        rootNavigationController.viewControllers.insert(tabBarController, at: 0) // Это на тот случай если у нас ранее были viewcontrollers и от них нужно уйти - к примеру контроллеры авторизации
        
        show(navigation: rootNavigationController, tabBarController, method: .normal) // А это чтобы с предыдущих контроллеров возвратиться с анимацией на этот
    }


Так же у меня есть специальная функция получения текущего navigationController с корневого tabbarcontroller
func basicContainerActiveNavigationController() -> UINavigationController? {
        var tabBarController: BasicTabContainerViewController? = nil
        for controller in rootNavigationController.viewControllers {
            if (controller.isKind(of: BasicContainerViewController.self)) {
                tabBarController = controller as? BasicContainerViewController
            }
        }
        
        return tabBarController?.selectedViewController as? UINavigationController
    }

Это все сделано так потому что у меня в приложении перед тем как отобразится корневой tabarcontroller происходит авторизация пользователя и проверка этого, и если пользователь не авторизован снова показывается окно авторизации - поэтому и существует rootnavigationcontroller, а для дальнейших переходов внутри tabbarcontroller я и сделал определение текущего активного navigationcontroller

Далее я перехожу на новый контроллер
func showNewController() {
        let viewController = getController(storyboard: "New") as! NewViewController
        
        guard let navigationCotnroller = basicContainerActiveNavigationController() else {
            return
        }
        show(navigation: navigationCotnroller, viewController, method: .normal)
    }


В общем такая замороченная навигация
  • Вопрос задан
  • 201 просмотр
Пригласить эксперта
Ответы на вопрос 1
YeahGarage
@YeahGarage
Developer
navigationController?.interactivePopGestureRecognizer?.isEnabled = true
navigationController?.interactivePopGestureRecognizer?.delegate = nil


extension UINavigationController: UINavigationControllerDelegate {
    
    open override func viewDidLoad() {
        super.viewDidLoad()
        self.delegate = self
    }
    
    public func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
        if responds(to: #selector(getter: self.interactivePopGestureRecognizer)) {
            if viewControllers.count > 1 {
                interactivePopGestureRecognizer?.isEnabled = true
            } else {
                interactivePopGestureRecognizer?.isEnabled = false
            }
        }
    }
}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы