swiftuinavigationcontrolleruisplitviewcontrollercoordinator-pattern

Coordinator Pattern to replace UINavigationController in SplitViewController


I am implementing coordinator pattern to handle navigation in my app. In theory when users choose different category I want to set the splitViewController to replace the existing navigationController for that category by a new one.

When app starts the coordinator operate as expected, and when I pop or push on the same navigationController implemented at start also works fine, my only problem is when I try to replace the whole navigationController of the splitviewcontroller.

ISSUE: adding new navigationController is not displayed to the user

here is my implementation.

class Coordinator: Navigable, DataCommunicator{
    //MARK: - Navigable Conformable
    typealias UIController = SplitController
    var viewController: UIController
    var childCoordinators: [Coordinatable] = []
    //MARK: - Root Custom setup
    weak var parentCoordinator: RootCoordinator?
    //MARK: - Init
    init(viewController: UIController) {
        self.viewController = viewController
    }

    func start() {
      let categoryNavigationController = CategoryNavigationController()
        let categoryNavigationCoordinator = CategoryNavigationCoordinator(viewController: noteNavigationController)
        categoryNavigationCoordinator.start()
        childCoordinators.append(categoryNavigationCoordinator)
        categoryNavigationController.coordinator = self     
        viewController.viewControllers = [categoryNavigationController]
    }
    func startSearchCategory() {
        childCoordinators.removeLast()
        viewController.navigationController?.popToRootViewController(animated: false)
        viewController.viewControllers.removeLast()

        let searchNavigationController = SearchNavigationController()
        let searchCoordinator = SearchNavigationCoordinator(viewController:searchNavigationController)
        searchCoordinator.start()
        childCoordinators.append(searchCoordinator)
        searchNavigationController.coordinator = self
        searchCoordinator.parentCoordinator = self
        viewController.viewControllers = [searchNavigationController]

    }

}

Solution

  • Update: I think I reached the desired behavior with a different approach, still I am curious why I can't display different navigationController for the masterController in the UISplitViewController and display it.

    But my approach helped my code to be more modular. I added in my Coordinator protocol the following function

        func stopChild<T: Coordinatable>(coordinator: T, callback: CoordinatorCallBack?)
    

    and implemented the function as the following:

      override func stopChild<T>(coordinator: T, callback: CoordinatorCallBack?) where T : Coordinatable {
            childCoordinators = childCoordinators.filter({$0 !== coordinator})
    // Calling parent to stop the child coordinator to roll back to the rootController
            parentCoordinator?.stopChild(coordinator: self, callback: nil)
    
     }
    

    Rolling back helped me to instantiate the full stack I desire without trying to add custom modifying code for the splitViewController, instead I am replacing the whole splitViewController with the one corresponding to the module I am working with, which is prettier for generic use. Since in my call back I can send to the root coordinator the desired module the user will be interested in next.