Home > OS >  How do I apply the coordinator pattern to the tabBar?
How do I apply the coordinator pattern to the tabBar?

Time:08-02

I want to apply the coordinator pattern to the tab bar.

first, my AppCoordinator


class AppCoordinator: Coordinator {
   let window: UIWindow?
   var navigationController: UINavigationController
   var childCoordinator: [Coordinator] = []
   var parentCoordinator: Coordinator?
    
    init(_ window: UIWindow?, navigationController: UINavigationController) {
        self.window = window
        self.navigationController = navigationController
        window?.makeKeyAndVisible()
    }
    
    func start() {
        var tabBarController = setTabBarController()
        self.window?.rootViewController = tabBarController
    }
    
    func setTabBarController() -> UITabBarController {
        let tabBar = UITabBarController()
        
        let firstItem = UITabBarItem(title: nil, image: Image.mainImg, tag: 0)
        let secondItem = UITabBarItem(title: nil, image: Image.searchImg, tag: 1)
        let thirdItem = UITabBarItem(title: nil, image: Image.likePostImg, tag: 2)
        let fourItem = UITabBarItem(title: nil, image: Image.profileImg, tag: 3)
        
        
        let firstCoordinator = MainCoordinator(navigationController: navigationController)
        firstCoordinator.parentCoordinator = self
        childCoordinator.append(firstCoordinator)
        let firstVC = firstCoordinator.startPush()
        firstVC.tabBarItem = firstItem
        
        let secondCoordinator = SearchCoordinator(navigationController: navigationController)
        secondCoordinator.parentCoordinator = self
        childCoordinator.append(secondCoordinator)
        let secondVC = secondCoordinator.startPush()
        secondVC.tabBarItem = secondItem
        
        let thirdCoordinator = LikePostCoordinator(navigationController: navigationController)
        thirdCoordinator.parentCoordinator = self
        childCoordinator.append(thirdCoordinator)
        let thirdVC = thirdCoordinator.startPush()
        thirdVC.tabBarItem = thirdItem
        
        tabBar.viewControllers = [firstVC, secondVC, thirdVC]
        
        return tabBar
    }
}


and my MainCoordinator


class MainCoordinator: baseCoordinator {

    func startPush() -> UINavigationController {
        
        let MainVC = MainViewController(viewModel: .init(coordinator: self))
        
        navigationController.setViewControllers([MainVC], animated: true)
        return navigationController
    }
}

searchVC and likePostVC are the same.

However, my execution result was as follows:

enter image description here

For quick explanation, only the code that seems necessary is shown. I wonder why my execution result is like this. Please help me

CodePudding user response:

I see two issues:

  1. make parentConordinator weak to prevent retain cycles
  2. you are passing the same navigationController to all your tab roots. That cannot work and is probably the reason for the problem you are seeing.

CodePudding user response:

I think you need a coordinator for your tabBarController. And in start of that coordinator you add your child coordinators to your tabBarCoordinator.

I always had login flow before tabBar, and on start of AppCoordinator I initialize login and set appCoordinator.rootViewController to loginCoordinator.rootViewController. This is how I use coordinators with tabBar:

class AppCoordinator() {
      func start() { 
      // Mostly initializing login.
      // somehow loginCoordinator triggers coordinatorDelegate.goToTabBar()
   }

   func goToTabBar() {
    tabBarCoordinator = TabBarCoordinator(root: root, dependencies: dependencies)
    tabBarCoordinator.coordinatorDelegate = self
    tabBarCoordinator.start()
   }
}

And here is how I start my TabBarCoordinator:

class TabBarCoordinator {
 func start() { 
     let tabBarController = TabBarController()
     
     let firstCoordinator = //
     children.append(firstCoordinator)]
     firstCoordinator.start()
     
     let controller1 = UIViewController()
     controller1 = firstCoordinator.rootViewController

    // Do the same for second..
    
   tabBarController.viewControllers = [controller1, controller2]
   rootViewController.show(tabBarController, sender: nil)
   }

And here is how to initialize sub coordinators:

class FirstCoordinator {
    func start() { 
     let firstVC = FirstViewController()
     let navController = UINavigationController(rootViewController: firstVC)
     rootViewController = navController
    }  
}

I tried to simplify the code, it might not the direct answer you are looking for but i think it will be helpful to understand the pattern. }

  • Related