diff --git a/TIDeepLink/Sources/Deeplink.swift b/TIDeepLink/Sources/Deeplink.swift index 5bbb3b45..1125fb6e 100644 --- a/TIDeepLink/Sources/Deeplink.swift +++ b/TIDeepLink/Sources/Deeplink.swift @@ -22,25 +22,25 @@ import Foundation -open class Deeplink: Equatable, Hashable { - - public var rawValue: String - - required public init(rawValue: String) { - self.rawValue = rawValue - } - - public static func == (lhs: Deeplink, rhs: Deeplink) -> Bool { - lhs.rawValue == rhs.rawValue - } - - public func hash(into hasher: inout Hasher) { - hasher.combine(rawValue) - } -} - -public extension Array where Element: Deeplink { - func find(byRawValue rawValue: String) -> Deeplink? { - first { $0.rawValue == rawValue } - } -} +//open class Deeplink: Equatable, Hashable { +// +// public var rawValue: String +// +// required public init(rawValue: String) { +// self.rawValue = rawValue +// } +// +// public static func == (lhs: Deeplink, rhs: Deeplink) -> Bool { +// lhs.rawValue == rhs.rawValue +// } +// +// public func hash(into hasher: inout Hasher) { +// hasher.combine(rawValue) +// } +//} +// +//public extension Array where Element: Deeplink { +// func find(byRawValue rawValue: String) -> Deeplink? { +// first { $0.rawValue == rawValue } +// } +//} diff --git a/TIDeepLink/Sources/DeeplinkHandler/BaseNavigationStackDeeplinkHandler.swift b/TIDeepLink/Sources/DeeplinkHandler/BaseNavigationStackDeeplinkHandler.swift index fed54d37..17824cc1 100644 --- a/TIDeepLink/Sources/DeeplinkHandler/BaseNavigationStackDeeplinkHandler.swift +++ b/TIDeepLink/Sources/DeeplinkHandler/BaseNavigationStackDeeplinkHandler.swift @@ -22,24 +22,57 @@ import Foundation import UIKit +import TISwiftUtils -open class BaseNavigationStackDeeplinkHandler: DeeplinkHandler { +open class BaseNavigationStackDeeplinkHandler: DeeplinkHandler { public var rootViewControllerKeeper: UIViewController + public var asAnyHandlerClosure: Closure?> + + public init(rootViewControllerKeeper: UIViewController, + asAnyHandlerClosure: @escaping Closure?>) { - public init(rootViewControllerKeeper: UIViewController) { self.rootViewControllerKeeper = rootViewControllerKeeper + self.asAnyHandlerClosure = asAnyHandlerClosure } // MARK: - DeeplinkHandler open func handle(deeplink: Deeplink) -> Operation? { - let handler = findHandler(for: deeplink) + let handler = asAnyHandlerClosure(rootViewControllerKeeper) ?? findHandler(for: deeplink, in: rootViewControllerKeeper) + return handler?.handle(deeplink: deeplink) } // MARK: - Open methods - open func findHandler(for deeplink: Deeplink) -> DeeplinkHandler? { - rootViewControllerKeeper.findHandler(for: deeplink) + open func findHandler(for deeplink: Deeplink, in viewController: UIViewController) -> AnyDeeplinkHandler? { + switch viewController { + case let navController as UINavigationController: + for controllerInNavigationStack in navController.viewControllers.reversed() { + if let handler = asAnyHandlerClosure(controllerInNavigationStack) { + return handler + } + } + + case let tabController as UITabBarController: + if let selectedController = tabController.selectedViewController, let handler = asAnyHandlerClosure(selectedController) { + return handler + } else if var tabControllers = tabController.viewControllers { + if tabController.selectedIndex != NSNotFound { + tabControllers.remove(at: tabController.selectedIndex) + } + + for tabController in tabControllers { + if let handler = asAnyHandlerClosure(tabController) { + return handler + } + } + } + + default: + return asAnyHandlerClosure(viewController) + } + + return nil } } diff --git a/TIDeepLink/Sources/DeeplinkHandler/DeeplinkHandler.swift b/TIDeepLink/Sources/DeeplinkHandler/DeeplinkHandler.swift index 6486521d..1c116497 100644 --- a/TIDeepLink/Sources/DeeplinkHandler/DeeplinkHandler.swift +++ b/TIDeepLink/Sources/DeeplinkHandler/DeeplinkHandler.swift @@ -23,5 +23,7 @@ import Foundation public protocol DeeplinkHandler { + associatedtype Deeplink + func handle(deeplink: Deeplink) -> Operation? } diff --git a/TIDeepLink/Sources/DeeplinkHandler/Helpers/UIViewController+DeeplinkHandler.swift b/TIDeepLink/Sources/DeeplinkHandler/Helpers/UIViewController+DeeplinkHandler.swift index 9a6a1314..3e5e6374 100644 --- a/TIDeepLink/Sources/DeeplinkHandler/Helpers/UIViewController+DeeplinkHandler.swift +++ b/TIDeepLink/Sources/DeeplinkHandler/Helpers/UIViewController+DeeplinkHandler.swift @@ -22,54 +22,30 @@ import UIKit -public extension UIViewController { - func findHandler(for deeplink: Deeplink) -> DeeplinkHandler? { - if let deeplinksHandler = self as? DeeplinkHandler, - let _ = deeplinksHandler.handle(deeplink: deeplink) { - return deeplinksHandler - } +enum ProjectDeeplink: Hashable { + case promoList + case promoDetails(String) +} - if let deeplinksHandler: DeeplinkHandler = presentedViewController?.findHandler(for: deeplink) { - return deeplinksHandler - } +protocol ProjectDeeplinkHandler: DeeplinkHandler where Deeplink == ProjectDeeplink {} - return findHandlerInViewHierarchy(for: deeplink) - } +final class ProjectDeeplinkService: TIDeeplinksService { +} - private func findHandlerInViewHierarchy(for deeplink: Deeplink) -> DeeplinkHandler? { - switch self { - case let navController as UINavigationController: - let deeplinksHandler = navController.viewControllers.reversed().findHandler(for: deeplink) - return deeplinksHandler - - case let tabController as UITabBarController: - if let deeplinksHandler = tabController.selectedViewController?.findHandler(for: deeplink) { - return deeplinksHandler - } else if var tabControllers = tabController.viewControllers { - if tabController.selectedIndex != NSNotFound { - tabControllers.remove(at: tabController.selectedIndex) - } - - if let deeplinksHandler = tabControllers.findHandler(for: deeplink) { - return deeplinksHandler - } - } - - default: - return nil - } - - return nil +final class ProjectVC: UIViewController, DeeplinkHandler { + func handle(deeplink: ProjectDeeplink) -> Operation? { + BlockOperation() } } -private extension Sequence where Element: UIViewController { - func findHandler(for deeplink: Deeplink) -> DeeplinkHandler? { - for controller in self { - if let deeplinksHandler = controller.findHandler(for: deeplink) { - return deeplinksHandler +final class ProjectNavigationHandler: BaseNavigationStackDeeplinkHandler { + convenience init() { + self.init(rootViewControllerKeeper: UIViewController()) { + guard let projectHandler = $0 as? (any ProjectDeeplinkHandler) else { + return nil } + + return projectHandler.eraseToAnyDeeplinkHandler() } - return nil } } diff --git a/TIDeepLink/Sources/DeeplinkMapper.swift b/TIDeepLink/Sources/DeeplinkMapper.swift index 01d7004f..30f71b19 100644 --- a/TIDeepLink/Sources/DeeplinkMapper.swift +++ b/TIDeepLink/Sources/DeeplinkMapper.swift @@ -23,5 +23,7 @@ import Foundation public protocol DeeplinkMapper { + associatedtype Deeplink + func map(url: URL) -> Deeplink? } diff --git a/TIDeeplink/Sources/TIDeeplinkService.swift b/TIDeeplink/Sources/TIDeeplinkService.swift index a2f4f5a2..2336a8f1 100644 --- a/TIDeeplink/Sources/TIDeeplinkService.swift +++ b/TIDeeplink/Sources/TIDeeplinkService.swift @@ -23,7 +23,46 @@ import Foundation import TIFoundationUtils -open class TIDeeplinksService { +import TISwiftUtils + +public struct AnyDeeplinkMapper: DeeplinkMapper { + private let mappingClosure: Closure + + public init(mapper: Mapper) where Mapper.Deeplink == Deeplink { + self.mappingClosure = mapper.map + } + + public func map(url: URL) -> Deeplink? { + mappingClosure(url) + } +} + +public extension DeeplinkMapper { + func eraseToAnyDeeplinkMapper() -> AnyDeeplinkMapper { + AnyDeeplinkMapper(mapper: self) + } +} + +public struct AnyDeeplinkHandler: DeeplinkHandler { + private let handlerClosure: Closure + + public init(handler: Handler) where Handler.Deeplink == Deeplink { + self.handlerClosure = handler.handle + } + + public func handle(deeplink: Deeplink) -> Operation? { + handlerClosure(deeplink) + } +} + +public extension DeeplinkHandler { + func eraseToAnyDeeplinkHandler() -> AnyDeeplinkHandler { + AnyDeeplinkHandler(handler: self) + } +} + + +open class TIDeeplinksService { // MARK: - Private properties @@ -34,17 +73,18 @@ open class TIDeeplinksService { // MARK: - Public properties - public var deeplinkMapper: DeeplinkMapper? - public var deeplinkHandler: DeeplinkHandler? + public var deeplinkMapper: AnyDeeplinkMapper? + public var deeplinkHandler: AnyDeeplinkHandler? // MARK: - Init - public init(mapper: DeeplinkMapper? = nil, - handler: DeeplinkHandler? = nil, - operationQueue: OperationQueue = .main) { + public init(mapper: Mapper? = nil, + handler: Handler? = nil, + operationQueue: OperationQueue = .main) + where Mapper.Deeplink == Deeplink, Handler.Deeplink == Deeplink { - self.deeplinkMapper = mapper - self.deeplinkHandler = handler + self.deeplinkMapper = mapper?.eraseToAnyDeeplinkMapper() + self.deeplinkHandler = handler?.eraseToAnyDeeplinkHandler() self.operationQueue = operationQueue }