Skip to content

Instantly share code, notes, and snippets.

@moderateepheezy
Last active May 3, 2020 11:00
Show Gist options
  • Save moderateepheezy/af9b41460629dcb69f5ececa1fa58912 to your computer and use it in GitHub Desktop.
Save moderateepheezy/af9b41460629dcb69f5ececa1fa58912 to your computer and use it in GitHub Desktop.
Deep linking iOS: A prototype of how you can implement deep linking with Coordinator in an iOS app
typealias Param = [AnyHashable: Any]?
/// We use `CordinatorActionFactory` in AppDelegate to process data
final class CordinatorActionFactory {
/// make a CoordinatorAction from url scheme data gotten from `CordinatorActionFactory`
func make(from urlSchemeHost: String, parameters: [String: Any]) -> CoordinatorAction? {
var params = parameters
params["type"] = urlSchemeHost
return CoordinatorAction(data: params)
}
/// make a CoordinatorAction from push notifications gotten from `CordinatorActionFactory`.
func make(from notification: [AnyHashable: Any]?) -> CoordinatorAction? {
return CoordinatorAction(data: notification)
}
}
/// This are the base route that get information and push to sub base route
enum CoordinatorAction {
case payment(paymentRoute: PaymentRoutes)
case services(serviceRoute: ServicesRoute)
init?(data: Param) {
guard let data = data,
let type = data["type"] as? String,
let routeType = RouteType.init(rawValue: type)
else { return nil }
switch routeType {
case .payToGomoney:
self = .payment(paymentRoute: .payMoney(data: data))
case .requestPayment:
self = .payment(paymentRoute: .request(data: data))
case .payForData:
self = .services(serviceRoute: .bills(data: data))
}
}
}
/// This is what the backend defined as the type of information coming into the device.
enum RouteType: String {
case payToGomoney = "gomoney"
case requestPayment = "requestGoMoney"
case payForData = "buyData"
}
/// This are the routes `Payment` tab can push to base on the `RouteType`
/// coming from push notifications or other external
/// source of information
enum PaymentRoutes {
case payMoney(data: Param)
case request(data: Param)
case root
}
/// This are the routes `Service` tab can push to base on the `RouteType`
/// coming from push notifications or other external
/// source of information
enum ServicesRoute {
case bills(data: Param)
case root
}
protocol Cordinator {
func process(action: CoordinatorAction?)
}
/// Using the process in the main coordinator: MainCoordinator creates and holds all tab items
class MainCordinator: Cordinator {
func process(action: CoordinatorAction?) {
guard let action = action else { return }
switch action {
case .payment:
tabBarController.selectedIndex = 2
paymentsCoordinator.process(action: action)
break
case .services:
tabBarController.selectedIndex = 3
servicesCoordinator.process(action: action)
break
}
}
}
// Using the process in the payments coordinator, where `PaymentsCordinator` is a tab item
class PaymentsCordinator: Cordinator {
func process(action: CoordinatorAction?) {
guard let action = action else { return }
switch action {
case .payment(let paymentRoute):
switch paymentRoute {
case .payMoney(let data):
print(data as Any)
break
case .request(let data):
print(data as Any)
break
case .root:
break
}
default:
break
}
}
}
/// Using the process in the services coordinator, where `ServicesCordinator` is a tab item
class ServicesCordinator: Cordinator {
func process(action: CoordinatorAction?) {
guard let action = action else { return }
switch action {
case .services(let serviceRoute):
switch serviceRoute {
case .bills(let data):
print(data as Any)
break
case .root:
break
}
default:
break
}
}
}
//** Simple Use case **//
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
private lazy var actionFactory = CoordinatorActionFactory()
private lazy var applicationCoordinator: ApplicationCoordinator = {
return ApplicationCoordinator(window: window!, container: container)
}()
// Get data from push notifcations
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
applicationCoordinator.process(action: self.actionFactory.make(from: userInfo))
}
/// Get data from custom url scheme
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
if let scheme = url.scheme,
scheme.localizedCaseInsensitiveCompare("scheme.something") == .orderedSame,
let host = url.host {
var parameters: [String: String] = [:]
URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems?.forEach {
parameters[$0.name] = $0.value
}
let action = self.actionFactory.make(from: host, parameters: parameters)
applicationCoordinator.process(action: action)
}
return true
}
}
@jogboms
Copy link

jogboms commented May 3, 2020

What happened to indentation?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment