From 49e2d18f14f49dc06e79629a1a91dd89bc9acd52 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Tue, 11 Apr 2023 14:30:53 +0200 Subject: [PATCH] Defined the Coordinator protocol. --- .../Sources/Core/Protocols/Coordinator.swift | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 Apps/Locations/Libraries/Sources/Core/Protocols/Coordinator.swift diff --git a/Apps/Locations/Libraries/Sources/Core/Protocols/Coordinator.swift b/Apps/Locations/Libraries/Sources/Core/Protocols/Coordinator.swift new file mode 100644 index 0000000..8563606 --- /dev/null +++ b/Apps/Locations/Libraries/Sources/Core/Protocols/Coordinator.swift @@ -0,0 +1,76 @@ +// +// Coordinator.swift +// Core +// +// Created by Javier Cicchelli on 11/04/2023. +// Copyright © 2023 Röck+Cöde. All rights reserved. +// + +/// This protocol organize the flow logic between view controllers in the app. +public protocol Coordinator: AnyObject { + + // MARK: Properties + + /// The child coordinators that are being currently presented. + var children: [Coordinator] { get set } + + /// The router that handles how the view controllers in the coordinators will be shown or dismissed. + var router: Router { get } + + // MARK: Functions + + /// Present the coordinator animatedly or not, dependencing on the given `animated` parameter, and also pass a closure that should be called on dismissal. + /// - Parameters: + /// - animated: A boolean that represents whether the coordinator should be dismissed animatedly or not. + /// - onDismissed: A closure to be called or executed when the presented coordinator is dismissed. + func present(animated: Bool, onDismissed: Router.OnDismissedClosure?) + +} + +// MARK: - Coordinator+Implementations + +public extension Coordinator { + + /// Present a child coordinator animatedly or not, dependencing on the given `animated` parameter, and also pass a closure that should be called on dismissal. + /// - Parameters: + /// - child: A child coordinator to be presented. + /// - animated: A boolean that represents whether the coordinator should be dismissed animatedly or not. + /// - onDismissed: A closure to be called or executed when the presented coordinator is dismissed. + func present( + child: Coordinator, + animated: Bool, + onDismissed: Router.OnDismissedClosure? = nil + ) { + store(child) + child.present(animated: animated) { [weak self, weak child] in + guard let self, let child else { + return + } + + self.free(child) + onDismissed?() + } + } + + /// Dismiss the coordinator animatedly or not, dependencing on the given `animated` parameter. + /// - Parameter animated: A boolean that represents whether the coordinator should be dismissed animatedly or not. + func dismiss(animated: Bool) { + router.dismiss(animated: animated) + } + +} + +// MARK: - Helpers + +private extension Coordinator { + + // MARK: Functions + + func store(_ coordinator: Coordinator) { + children.append(coordinator) + } + + func free(_ coordinator: Coordinator) { + children = children.filter { $0 !== coordinator } + } +}