From b76b36d6f1206dcd946546ccf937135d1de88432 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Tue, 11 Apr 2023 15:01:44 +0200 Subject: [PATCH] Implemented the NavigationRouter router. --- .../Core/Routers/NavigationRouter.swift | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 Apps/Locations/Libraries/Sources/Core/Routers/NavigationRouter.swift diff --git a/Apps/Locations/Libraries/Sources/Core/Routers/NavigationRouter.swift b/Apps/Locations/Libraries/Sources/Core/Routers/NavigationRouter.swift new file mode 100644 index 0000000..688c8ce --- /dev/null +++ b/Apps/Locations/Libraries/Sources/Core/Routers/NavigationRouter.swift @@ -0,0 +1,105 @@ +// +// NavigationRouter.swift +// Core +// +// Created by Javier Cicchelli on 11/04/2023. +// Copyright © 2023 Röck+Cöde. All rights reserved. +// + +import UIKit + +/// This class is responsible for presenting view controllers, as it is a concrete implementation of the `Router` protocol, but it won't know what view controller or which view controller is next. +public class NavigationRouter: NSObject { + + // MARK: Properties + + /// A navigation controller to use within this concrete router. + private let navigationController: UINavigationController + + /// A root view controller coming in from the navigation controller, if any. + private let rootViewController: UIViewController? + + /// Dictionary that persist `onDismiss` closure for its respective view controllers until one of the later is dismissed. + private var onDismissForViewController: [UIViewController: Router.OnDismissedClosure] = [:] + + // MARK: Initialisers + + /// Initialise this router. + /// - Parameter navigationController: A `UINavigationController` navigation controller instance to use in this router. + public init(navigationController: UINavigationController) { + self.navigationController = navigationController + self.rootViewController = navigationController.viewControllers.first + + super.init() + + self.navigationController.delegate = self + } + +} + +// MARK: - Router + +extension NavigationRouter: Router { + + // MARK: Functions + + public func present( + _ viewController: UIViewController, + animated: Bool, + onDismiss: OnDismissedClosure? + ) { + onDismissForViewController[viewController] = onDismiss + + navigationController.pushViewController(viewController, animated: animated) + } + + public func dismiss(animated: Bool) { + guard let rootViewController else { + navigationController.popViewController(animated: animated) + return + } + + performOnDismissed(for: rootViewController) + + navigationController.popToViewController(rootViewController, animated: animated) + } + +} + +// MARK: - UINavigationControllerDelegate + +extension NavigationRouter: UINavigationControllerDelegate { + + // MARK: Functions + + public func navigationController( + _ navigationController: UINavigationController, + didShow viewController: UIViewController, + animated: Bool + ) { + guard let dismissedViewController = navigationController.transitionCoordinator?.viewController(forKey: .from) else { + return + } + + performOnDismissed(for: dismissedViewController) + } + +} + +// MARK: - Helpers + +private extension NavigationRouter { + + // MARK: Functions + + func performOnDismissed(for viewController: UIViewController) { + guard let onDismiss = onDismissForViewController[viewController] else { + return + } + + onDismiss() + + onDismissForViewController[viewController] = nil + } + +}