/** Maintains the state needed to implement your own `UITabController` replacement, without making any assumptions about how your UI looks or works. */ public final class TabItemViewControllerRouter { /// The tab bar items for the view controllers. You can use these when constructing your UI’s buttons public let tabItems: [TabItem] // MARK: - Immutable private state /// The view controllers that can be routed between private let viewControllers: [UIViewController] /// Mapping of tab bar items to view controllers private let tabItemsToViewControllers: [TabItem: UIViewController] /// The container view controller serving as the `UITabController` replacement private weak var parentViewController: UIViewController? /// A function for adding a view to the container view controller’s hierarchy private let viewHierarchyUpdater: UIView -> Void // MARK: - Mutable private state /// The currently selected view controller private var selectedViewController: UIViewController? // MARK: - Initialization /** Create a new tab bar item view controller router. - parameter viewControllers: The view controllers that can be routed between - parameter parentViewController: The container view controller serving as the `UITabController` replacement - parameter viewHierarchyUpdater: A function for adding a view to the container view controller’s hierarchy - returns: New instance */ public init(tabComponents: [TabComponent], parentViewController: UIViewController, viewHierarchyUpdater: UIView -> Void) { self.viewControllers = tabComponents.map { $0.viewController } self.parentViewController = parentViewController self.viewHierarchyUpdater = viewHierarchyUpdater self.tabItems = tabComponents.map { $0.tabItem } self.tabItemsToViewControllers = Dictionary(zip(tabItems, viewControllers)) } /** Route based on a new tab bar item having been selected. - parameter tabItem: Selected tab bar item */ public func selectTabItem(tabItem: TabItem) { guard let viewController = tabItemsToViewControllers[tabItem] else { return } selectViewController(viewController) } /** Update which view controller is the selected one. - parameter viewController: Selected view controller */ private func selectViewController(viewController: UIViewController) { let oldValue = selectedViewController oldValue?.willMoveToParentViewController(nil) parentViewController?.addChildViewController(viewController) viewHierarchyUpdater(viewController.view) oldValue?.removeFromParentViewController() viewController.didMoveToParentViewController(parentViewController) selectedViewController = viewController } }