DeepCoordinatorKit
Lightweight library that pass deeplinks trought coordiantor tree and respond on them. Depends on CoordinatorKit.
Navigation
Installation
Ready to use on iOS 9+. iOS only.
Swift Package Manager
In Xcode go to File
→ Packages
→ Update to Latest Package Versions
and insert url:
https://github.com/kotostrophe/DeepCoordiantorKit
or add it to the dependencies
value of your Package.swift
:
dependencies: [
.package(url: "https://github.com/kotostrophe/DeepCoordinatorKit", .upToNextMajor(from: "1.0.0")),
]
Manually
If you prefer not to use any of dependency managers, you can integrate manually. Put Sources/DeepCoordiantorKit
folder in your Xcode project. Make sure to enable Copy items if needed
and Create groups
.
Library is developed with dependency of another library called CoordinatorKit. If you decided to add this library manually then do that with depended part.
Usage
DeepLinkResponder
it's a base protocol that help to pass deeplink throught the nodes. By default protocol DeepLinkResponder
uses only Coordinatable
protocol from CoordinatorKit. It help for building tree-like structure from nodes.
public protocol DeepLinkResponder: AnyObject {
var deepLinkLocator: DeepLinkLocatorProtocol { get } // store all the deeplink handler for this object
func becomeFirstResponder(child: DeepLinkResponder?) // run in case of first responder
func canRespond(on path: String) -> Bool // supplementary method for seeking target handler
func respond(on path: String) // activates handler that respond on deeplink path
func hitTest(with path: String) -> DeepLinkResponder? // mechanism of finding target deeplink handler
}
Deeplink passing throught the initial node (root) and searching node that can respond on it.
Protocol DeepLinkResponder
have default body methods. Check that in file Coordinatable+DeepLinkResponder.swift
Default realization of canRespond(on:)
method compare all available routes with deeplink route path. If any route with similar path exists then return true
.
func canRespond(on path: String) -> Bool {
deepLinkLocator.routes
.contains(where: { route in path == route })
}
Default realization of respond(on:)
method find first responder with similar path and prepare action if handler exists.
func respond(on path: String) {
deepLinkLocator.routes
.first(where: { route in path == route })?
.prepareAction(with: path)()
}
hitTest(with:)
it is main method of handling deeplink. It composit two previous methods canRespond(on:)
and respond(on:)
. It uses recoursive mechanism to find deeplink responder. By the structure it looks like graph depth-first search.
hitTest(with:)
must be called to the initial point (root) of coordinators tree
func hitTest(with path: String) -> DeepLinkResponder? {
if canRespond(on: path) { return self }
for targetResponder in childLocator.coordiantors.compactMap({ $0 as? DeepLinkResponder }) {
guard let targetResponder = targetResponder.hitTest(with: path) else { continue }
return targetResponder
}
return nil
}
Example
applicationCoordinator
uses a initial point of nodes tree. When deeplink passes trought the application it activates method findFirstResponderIfNeeded(of:)
that run method hitTest(with:)
inside of it. When responder will be found it will respond on deeplink.
import UIKit
final class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// MARK: - Properties
var applicationCoordinator: ApplicationCoordinatorProtocol?
var window: UIWindow?
// MARK: - UIWindowSceneDelegate
...
func scene(_ scene: UIScene, openURLContexts urlContexts: Set<UIOpenURLContext>) {
findFirstResponderIfNeeded(of: urlContexts.first?.url.path)
}
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
findFirstResponderIfNeeded(of: userActivity.webpageURL?.path)
}
// MARK: - Deeplink
func findFirstResponderIfNeeded(of deeplinkPath: String?) {
guard let path = deeplinkPath else { return }
guard let firstResponder = applicationCoordinator?.hitTest(with: path) else { return }
firstResponder.becomeFirstResponder(child: nil)
firstResponder.respond(on: path)
}
}
Example app
In the repository deeplink-responder presented example of coordiantor pattern via using CoordinatorKit
. As an addition there was developed deeplink handling mechanism via DeepCoordinatorKit
.