I want to share an example for this question. My approach a little bit different and TabCoordinator not contains everything in his body. Instead of this, every coordinator has relation with its controller and in every UIViewController (in tabbar controller) has its UITabBarController reference like delegation pattern.
class Coordinator {
var navigationController: UINavigationController?
var childCoordinators: [Coordinator] = [Coordinator]()
init(with navigation: UINavigationController) {
self.navigationController = navigation
}
func start() {}
}
Then here is the coordinators.
Home Coordinator
final class HomeCoordinator: Coordinator {
var currentController: HomeController?
weak var tabController: TabController?
override init(with navigation: UINavigationController) {
super.init(with: navigation)
currentController = HomeController()
currentController?.coordinator = self
childCoordinators.append(self)
}
override func start() {
navigationController?.pushViewController(currentController ?? UIViewController(),
animated: true)
}
public func getHomeData() {
// GETTING HOME DATA
tabController?.requestFromHomeController()
}
}
About Coordinator
final class AboutCoordinator: Coordinator {
var currentController: AboutController?
weak var tabController: TabController?
override init(with navigation: UINavigationController) {
super.init(with: navigation)
currentController = AboutController()
currentController?.coordinator = self
childCoordinators.append(self)
}
override func start() {
navigationController?.pushViewController(currentController ?? UIViewController(),
animated: true)
}
public func getAboutData() {
// GETTING ABOUT DATA
tabController?.requestFromAboutController()
}
}
UITabBarController
final class TabController: UITabBarController {
weak var coordinator: MainTabCoordinator?
override func viewDidLoad() {
super.viewDidLoad()
let navigationController1 = UINavigationController()
let coordinator1 = HomeCoordinator(with: navigationController1)
coordinator1.tabController = self
coordinator1.currentController?.tabBarItem = UITabBarItem(title: "HOME",
image: nil,
tag: 11)
let navigationController2 = UINavigationController()
let coordinator2 = AboutCoordinator(with: navigationController2)
coordinator2.tabController = self
coordinator2.currentController?.tabBarItem = UITabBarItem(title: "ABOUT",
image: nil,
tag: 22)
viewControllers = [
coordinator1.currentController!,
coordinator2.currentController!
]
tabBar.barTintColor = UIColor.white
tabBar.isTranslucent = false
}
public func requestFromHomeController() {
print("Home Triggered the function")
coordinator?.fetchHome(with: "Simple Data",
completion: { (dictionary, error) in
print("dict from home -> ", dictionary)
})
}
public func requestFromAboutController() {
print("About Triggered the function")
coordinator?.handleAbout(with: "Simple Data",
completion: { (dictionary, error) in
print("dict from about -> ", dictionary)
})
}
}
Prepare the app from AppDelegate
in application(_ application: UIApplication, didFinishLaunchingWithOptions function
let appNavigationController = UINavigationController()
let tabCoordinator = MainTabCoordinator(with: appNavigationController ?? UINavigationController())
tabCoordinator.start()
window?.rootViewController = appNavigationController
Here is the AboutController
final class AboutController: UIViewController{
weak var coordinator: AboutCoordinator?
// define a button and add its target to handleButton function
@objc private func handleButton(_ sender: UIButton) {
coordinator?.getAboutData()
}
override func viewDidLoad() {
super.viewDidLoad()
// ui settings
}
}
MainTabCoordinator
final class MainTabCoordinator: Coordinator {
var currentController: TabController?
override init(with navigation: UINavigationController) {
super.init(with: navigation)
self.currentController = TabController()
self.childCoordinators.append(self)
currentController?.coordinator = self
}
override func start() {
navigationController?.pushViewController(currentController ?? UIViewController(),
animated: true)
}
func fetchHome(with title: String, completion: @escaping (_ result: Dictionary<String,Any>, _ error: NSError?) -> ()) {
completion(["ss":"ss"], nil)
}
func handleAbout(with title: String, completion: @escaping (_ result: Dictionary<String,Any>, _ error: NSError?) -> ()) {
completion(["ss":"ss"], nil)
}
}
The working schema is like that below:
AboutController ---> triggered action ---> AboutCoordinator ---> TabBarController reference has request to about action ----> MainTabCoordinator handle works.