Last active
May 3, 2020 11:00
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| |
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 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
What happened to indentation?