-
Notifications
You must be signed in to change notification settings - Fork 279
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: internal router #61
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -116,21 +116,17 @@ - (BOOL)handleURL:(NSURL *)url withCompletion:(DPLRouteCompletionBlock)completio | |
return NO; | ||
} | ||
|
||
NSError *error; | ||
DPLDeepLink *deepLink; | ||
__block BOOL isHandled = NO; | ||
for (NSString *route in self.routes) { | ||
DPLRouteMatcher *matcher = [DPLRouteMatcher matcherWithRoute:route]; | ||
deepLink = [matcher deepLinkWithURL:url]; | ||
if (deepLink) { | ||
isHandled = [self handleRoute:route withDeepLink:deepLink error:&error]; | ||
break; | ||
} | ||
} | ||
|
||
id handler; | ||
deepLink = [self deepLinkForUrl:url handler:&handler]; | ||
|
||
NSError *error; | ||
BOOL isHandled = NO; | ||
if (!deepLink) { | ||
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@"The passed URL does not match a registered route.", nil) }; | ||
error = [NSError errorWithDomain:DPLErrorDomain code:DPLRouteNotFoundError userInfo:userInfo]; | ||
} else { | ||
isHandled = [self handleRoute:handler withDeepLink:deepLink error:&error]; | ||
} | ||
|
||
[self completeRouteWithSuccess:isHandled error:error]; | ||
|
@@ -147,45 +143,84 @@ - (BOOL)handleUserActivity:(NSUserActivity *)userActivity withCompletion:(DPLRou | |
return NO; | ||
} | ||
|
||
- (UIViewController <DPLTargetViewController> *)viewControllerForUrl:(NSURL *)url { | ||
DPLDeepLink *deepLink; | ||
id handler; | ||
deepLink = [self deepLinkForUrl:url handler:&handler]; | ||
if (handler) { | ||
DPLRouteHandler *routeHandler = [self routeHandlerForHandler:handler]; | ||
if (routeHandler) { | ||
return [self viewControllerForHandler:routeHandler withDeepLink:deepLink]; | ||
} | ||
} | ||
return nil; | ||
} | ||
|
||
- (BOOL)handleRoute:(NSString *)route withDeepLink:(DPLDeepLink *)deepLink error:(NSError *__autoreleasing *)error { | ||
id handler = self[route]; | ||
|
||
if ([handler isKindOfClass:NSClassFromString(@"NSBlock")]) { | ||
DPLRouteHandlerBlock routeHandlerBlock = handler; | ||
routeHandlerBlock(deepLink); | ||
|
||
- (DPLDeepLink *)deepLinkForUrl:(NSURL *)url handler:(id *)handler { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that an inout parameter isn't ideal here. Maybe this method could return a dictionary? Or we could even create a lightweight class that had There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I almost created that lightweight class. IMO is the best option since we don't have tuples in Objective C. :) |
||
DPLDeepLink *deepLink; | ||
for (NSString *route in self.routes) { | ||
DPLRouteMatcher *matcher = [DPLRouteMatcher matcherWithRoute:route]; | ||
deepLink = [matcher deepLinkWithURL:url]; | ||
if (deepLink) { | ||
*handler = self[route]; | ||
break; | ||
} | ||
} | ||
else if (class_isMetaClass(object_getClass(handler)) && | ||
[handler isSubclassOfClass:[DPLRouteHandler class]]) { | ||
DPLRouteHandler *routeHandler = [[handler alloc] init]; | ||
return deepLink; | ||
} | ||
|
||
|
||
- (BOOL)handleRoute:(id)handler withDeepLink:(DPLDeepLink *)deepLink error:(NSError *__autoreleasing *)error { | ||
DPLRouteHandler *routeHandler = [self routeHandlerForHandler:handler]; | ||
if (routeHandler) { | ||
if (![routeHandler shouldHandleDeepLink:deepLink]) { | ||
return NO; | ||
} | ||
|
||
UIViewController *presentingViewController = [routeHandler viewControllerForPresentingDeepLink:deepLink]; | ||
UIViewController <DPLTargetViewController> *targetViewController = [routeHandler targetViewController]; | ||
UIViewController <DPLTargetViewController> *targetViewController = [self viewControllerForHandler:routeHandler withDeepLink:deepLink]; | ||
|
||
if (targetViewController) { | ||
[targetViewController configureWithDeepLink:deepLink]; | ||
[routeHandler presentTargetViewController:targetViewController inViewController:presentingViewController]; | ||
} | ||
else { | ||
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@"The matched route handler does not specify a target view controller.", nil)}; | ||
|
||
NSDictionary *userInfo = @{NSLocalizedDescriptionKey : NSLocalizedString(@"The matched route handler does not specify a target view controller.", nil)}; | ||
|
||
if (error) { | ||
*error = [NSError errorWithDomain:DPLErrorDomain code:DPLRouteHandlerTargetNotSpecifiedError userInfo:userInfo]; | ||
} | ||
|
||
return NO; | ||
} | ||
} | ||
|
||
else if ([handler isKindOfClass:NSClassFromString(@"NSBlock")]) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This might cause a problem in the future if the private class name changes. Can we just create a throwaway There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could certainly do that. That line is actually a copy from what was already in place on the code. I just had to move it to extract things from the methods. But from what I've seen, we can have two kinds of blocks, with and without a |
||
DPLRouteHandlerBlock routeHandlerBlock = handler; | ||
routeHandlerBlock(deepLink); | ||
} | ||
|
||
return YES; | ||
} | ||
|
||
|
||
- (DPLRouteHandler *)routeHandlerForHandler:(id)handler { | ||
if (class_isMetaClass(object_getClass(handler)) && | ||
[handler isSubclassOfClass:[DPLRouteHandler class]]) { | ||
return [[handler alloc] init]; | ||
} | ||
return nil; | ||
} | ||
|
||
|
||
- (UIViewController <DPLTargetViewController> *)viewControllerForHandler:(DPLRouteHandler *)routeHandler withDeepLink:(DPLDeepLink *)deepLink { | ||
UIViewController <DPLTargetViewController> *targetViewController; | ||
targetViewController = [routeHandler targetViewController]; | ||
[targetViewController configureWithDeepLink:deepLink]; | ||
return targetViewController; | ||
} | ||
|
||
|
||
- (void)completeRouteWithSuccess:(BOOL)handled error:(NSError *)error { | ||
|
||
dispatch_async(dispatch_get_main_queue(), ^{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
@class DPLRouteHandler; | ||
|
||
@interface DPLTestRouteHandler : DPLRouteHandler | ||
@end | ||
|
||
@interface TestViewController : UIViewController<DPLTargetViewController> | ||
@end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#import "DPLRouteHandler.h" | ||
#import "DPLTestRouteHandler.h" | ||
|
||
@implementation DPLTestRouteHandler | ||
- (UIViewController <DPLTargetViewController> *)targetViewController { | ||
return [[TestViewController alloc] init]; | ||
} | ||
@end | ||
|
||
@implementation TestViewController | ||
- (void)configureWithDeepLink:(DPLDeepLink *)deepLink {} | ||
@end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
URL should be uppercase here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok! Will do that for every URL in the code.