-
Notifications
You must be signed in to change notification settings - Fork 280
DeepLink Kit Integration Guide
DeepLink Kit is a splendid route-handling block-based way to handle deep links. Rather than decide how to format your URLs, parse them, pass data, and navigate to specific content or perform actions, this library and a few lines of code will get you on your way.
pod try DeepLinkKit
Note: Want to play with the source? Check it out
The best way to get the DeepLink Kit is to use CocoaPods. If you don't already use CocoaPods, the CocoaPods Getting Started Guide will have you managing dependencies in no time.
Add the following line to your Podfile.
pod "DeepLinkKit"
Import DeepLink Kit as follows:
#import <DeepLinkKit/DeepLinkKit.h>
To get started, you'll create an instance of DPLDeepLinkRouter
. Since the URLs are received in your AppDelegate
, create a property for your router and initialize it in -application:didFinishLaunchingWithOptions:
.
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.router = [[DPLDeepLinkRouter alloc] init];
return YES;
}
To handle incoming URLs in your app, you'll implement application:openURL:sourceApplication:annotation:
in your app delegate and pass the URL to the router.
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
return [self.router handleURL:url withCompletion:NULL];
}
If your application supports universal links introduced in iOS 9, implement the following in your app delegate:
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray *))restorationHandler {
return [self.router handleUserActivity:userActivity
withCompletion:NULL];
}
Registering a route is easy. Registering your first route can be done in just one line of code:
Note: As of 0.2.0
, in all registered routes, paths are considered to begin at the first forward slash. A route component before the first forward slash will be considered the host.
self.router[@"/say/hello"] = ^{
NSLog(@"Hello World!");
};
Now if your app receives a URL with a path of /say/hello
, it would log “Hello World!” to the console.
You can register dynamic routes just as easily:
self.router[@"/alert/:title/:message"] = ^(DPLDeepLink *link){
[[[UIAlertView alloc] initWithTitle:link.routeParameters[@"title"]
message:link.routeParameters[@"message"]
delegate:nil
cancelButtonTitle:NSLocalizedString(@"OK", nil)
otherButtonTitles:nil] show];
};
Now if your app receives a URL with a path of /alert/Hello/World
, your app would display the following alert:
Routes are matched in the order they were registered. The first route that matches the incoming URL is the one that gets handled. For example, given an incoming URL path of /say/hello
, if you had registered the following two routes, the second route would not get matched:
self.router[@"/say/hello"] = ^{
NSLog(@"Hello World!");
};
self.router[@"/say/:hello"] = ^{
// This block is never called.
};
URLs coming into your app will be in a similar format to the following:
<scheme>://<host>/<path-component>/<path-component>
When registering routes, it's important to note that the first forward slash in your registered route determines the start of the path to be matched. A route component before the first forward slash will be considered to be the host.
Say you have an incoming URL of twitter://timeline
// Matches the URL.
router[@"timeline"] = ^{ … }
// Does not match the URL.
router[@"/timeline"] = ^{ … }
In another example, a URL of twitter://dpl.com/timeline
// Matches the URL.
router[@"/timeline"] = ^{ … }
// Does not match the URL.
router[@"timeline"] = ^{ … }
When you register routes, you also specify the route handler to be used when handling a matching route. There are two type of route handlers.
Block handlers are great for simple cases such as performing an action in your app without any UI, or displaying a simple modal. Basically, block handlers leave all the work up to you. When an incoming URL is matched against a route, we'll call your block, pass you the parsed` deep link, and you do the rest.
The block type to use when specifying your route handler is DPLRouteHandlerBlock
. The block takes one parameter, an instance of DPLDeepLink
, the parsed object representation of the incoming deep link. You may omit the block parameter if you don't need it. For example, the following are valid ways to register a block-based handler for your routes:
router[@"/say/hello"] = ^{ };
router[@"/say/hello"] = ^(DPLDeepLink *deepLink) { };
Class-based handlers help simplify more complex situations where you want to map a route to a specific view controller. To create a class-based handler, create a subclass of DPLRouteHandler
. In your subclass, at a minimum, you must override -targetViewController
and return a view controller conforming to the DPLTargetViewController
protocol.
@implementation ProductRouteHandler
- (UIViewController <DPLTargetViewController> *)targetViewController {
return [[ProductDetailViewController alloc] init];
}
@end
Once you have your route handler subclass, you'll register it just as easily as a block-based handler.
self.router[@"/product/:product_id"] = [ProductRouteHandler class];
If your app receives a URL with a path of /product/abc123
, the router will instantiate your route handler subclass which will automatically display your target view controller.
Your target view controller conforms to the DPLTargetViewController
protocol, so you'll implement configureWithDeepLink:
where you'll receive the DPLDeepLink
instance and configure whatever content, action, etc is necessary to fulfill the use case.
@implementation ProductDetailViewController
- (void)configureWithDeepLink:(DPLDeepLink *)deepLink {
// Get the data you need from the deep link to configure your view controller.
NSString *productId = deepLink.routeParameters[@"product_id"];
self.product = [Product productWithId:productId];
}
@end
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Setup your DeepLink router.
self.router = [[DPLDeepLinkRouter alloc] init];
// Register a route handler.
self.router[@"/say/:title/:message"] = ^(DPLDeepLink *link) {
[[[UIAlertView alloc] initWithTitle:link.routeParameters[@"title"]
message:link.routeParameters[@"message"]
delegate:nil
cancelButtonTitle:NSLocalizedString(@"OK", nil)
otherButtonTitles:nil] show];
};
// Present a view controller from a route handler.
self.router[@"/product/:product_id"] = ^(DPLDeepLink *link) {
// Configure your view controller with the incoming product id.
ProductDetailViewController *controller = [[ProductDetailViewController alloc] init];
controller.productId = link.routeParameters[@"product_id"];
// Present the view controller.
[self.window.rootViewController presentViewController:controller
animated:NO
completion:NULL];
};
// Register a class-based route handler.
self.router[@"/event/:event_id"] = [EventRouteHandler class];
return YES;
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
[self.router handleURL:url withCompletion:^(BOOL handled, NSError *error) {
NSLog(@"Handled URL");
}];
return YES;
}