【问题标题】:Can not remove child coordinator because transitionCoordinator is nil in navigationController delegate method无法移除子协调器,因为在 navigationController 委托方法中 transitionCoordinator 为 nil
【发布时间】:2019-07-24 12:12:07
【问题描述】:

简介:

我已经实现了Soroush's 协调器架构。除了删除以前(子)协调员所需的删除部分外,一切正常。

场景:

我有两个ViewController,分别命名为HomeViewControllerMyGroupsViewController。每个都有自己的协调器,分别命名为 HomeCoordinatorMyGroupsCoordinator

用户点击HomeViewController 上的一个按钮,触发gotoMyGroupsTapped 函数并将用户带到MyGroupsViewController,然后用户点击MyGroupsViewController 上的另一个按钮,通过触发@987654333 让用户回到HomeViewController @。

很简单! : HomeVC -> MyGroupsVC -> HomeVC

但问题是:

navigationController.transitionCoordinator? 在两个协调器中的func navigationController(..., didShow viewController: UIViewController...) 中为 nil,我无法在每个转换中删除子协调器。

在两个协调器的start() func 中设置navigationController.delegate = self 是否正确?

我应该在我的backToHomePage() 函数中使用navigationController?.popViewController(animated: false ) 吗?因为Paul Hudson 只使用了pushViewController

我的代码 [简化版]:

HomeCoordinator.swift

import Foundation
import UIKit

class HomeCoordinator: NSObject,Coordinator,UINavigationControllerDelegate {
    var childCoordinators = [Coordinator]()
    var navigationController: UINavigationController
    weak var parentCoordinator : Coordinator?
    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }

     func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
         // Transition here is nil
         print(" Transition : ",navigationController.transitionCoordinator)
         guard let fromViewController = navigationController.transitionCoordinator?.viewController(forKey: .from) else {
             print("Unknown fromViewController!")
             return
         }
         // Removing a child coordinator
     }

    func gotoMyGroups (){
         let groupsCoordinator = GroupsCoordinator(navigationController: navigationController)
         childCoordinators.append(groupsCoordinator)
         groupsCoordinator.parentCoordinator = self
         groupsCoordinator.start()
      }

     func start() {
        let vc = HomeViewController.instantiate()
        vc.coordinator = self
        navigationController.delegate = self
        navigationController.pushViewController(vc, animated: false)
        navigationController.setNavigationBarHidden(true, animated: false)
     }
}

MyGroupsCoordinator.swift

import Foundation
import UIKit

class MyGroupsCoordinator: NSObject,Coordinator,UINavigationControllerDelegate {
    var childCoordinators = [Coordinator]()
    var navigationController: UINavigationController
    weak var parentCoordinator : Coordinator?
    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }

     func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
         // Transition here is nil
         print(" Transition : ",navigationController.transitionCoordinator)
         guard let fromViewController = navigationController.transitionCoordinator?.viewController(forKey: .from) else {
             print("Unknown fromViewController!")
             return
         }
         // Removing a child coordinator
     }

     func start() {
        let vc = MyGroupViewController.instantiate()
        vc.coordinator = self
        navigationController.delegate = self
        navigationController.pushViewController(vc, animated: false)
        navigationController.setNavigationBarHidden(true, animated: false)
     }
}

MyGroupViewController.magik

class MyGroupViewController :  UIViewControllerWithCoordinator,UITextFieldDelegate,Storyboarded{

     @IBAction func gotoHomePage(_ sender: Any) {
         if let coord = coordinator as? GroupsCoordinator {
             coord.parentCoordinator?.start()
         }
     }
 }

HomeViewController.swift

 class HomeViewController: UIViewControllerWithCoordinator,Storyboarded {
     @IBAction func gotoMyGroupsTapped(_ sender: Any) {
         guard let acoordinator = coordinator as? HomeCoordinator else {
             return
         }
         acoordinator.gotoMyGroups()
     }

【问题讨论】:

  • 你解决了吗?我有类似的问题,我发现当我从子协调器中删除 navigationController.delegate = self 时,子协调器的删除被执行,而不是当子被设置为导航控制器的委托时

标签: swift uinavigationcontroller coordinator-pattern transition-coordinator


【解决方案1】:

在我看来,这里的协调器模式使用存在混淆。

根据您的预期流程HomeVC -> MyGroupsVC -> HomeVC,如果您的意思是level1 -> level2 -> level3,那么GroupsCoordinator 应该使用自己的新HomeVC 创建一个新的HomeCoordinator 实例。

所以代替你以前的代码

class MyGroupViewController ... {
    @IBAction func gotoHomePage(_ sender: Any) {
        if let coord = coordinator as? GroupsCoordinator {
            coord.parentCoordinator?.start()
        }
    }
}

我会改成

class MyGroupViewController ... {
    @IBAction func gotoHomePage(_ sender: Any) {
        if let coord = coordinator as? GroupsCoordinator {
            coord.goToHome()
        }
    }
}

class MyGroupsCoordinator ... {

    func goToHome() {
        let homeCoordinator = HomeCoordinator(navigationController: navigationController)
        childCoordinators.append(homeCoordinator)
        groupsCoordinator.parentCoordinator = self
        groupsCoordinator.start()
    }
}

这将允许您创建一个全新的页面,如您所描述的那样HomeVC -> MyGroupsVC -> HomeVC


但是,如果您的意思是这种方法level1 -> level2 -> (back) level1,那么您需要终止MyGroupsCoordinator 并在导航返回时从父级中删除。

如您所见,为此,您需要使用 UINavigationControllerDelegate 才能在用户返回时收到通知(弹出代码或使用经典的返回按钮)。

我发现的一个解决方案是使用Router 来处理所有这些导航,当从其中删除UIViewController 时,还可以通过闭包通知要删除的正确协调器。你可以阅读更多关于它的信息here

希望对你有帮助

【讨论】:

    猜你喜欢
    • 2020-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多