Skip to content

Commit

Permalink
Deep link support (#5)
Browse files Browse the repository at this point in the history
* Added failure block

* Default configuration & bug fixes (#3)

* Fixed: Now is not executing execution callback if error is provided in protection block

* Added casting separator to default configuration

* Url types (#4)

* Added support for URL-s

* Update url swizzling

* Removed swizzling

* Fix animate reading from configuration

* Fix warnings
  • Loading branch information
aronbalog committed Jul 21, 2016
1 parent b0fbfb4 commit 3c30d01
Show file tree
Hide file tree
Showing 28 changed files with 456 additions and 324 deletions.
4 changes: 2 additions & 2 deletions ARoute.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|

s.name = "ARoute"
s.version = "0.0.6"
s.version = "0.0.7"
s.summary = "ARoute"

s.description = <<-DESC
Expand All @@ -14,7 +14,7 @@ Pod::Spec.new do |s|
s.platform = :ios
s.platform = :ios, "7.0"

s.source = { :git => "https://github.com/aronbalog/ARoute.git", :tag => "0.0.6" }
s.source = { :git => "https://github.com/aronbalog/ARoute.git", :tag => "0.0.7" }
s.source_files = "ARoute", "ARoute/**/*.{h,m}"
s.public_header_files = "ARoute/Classes/Public/**/*.h"
s.requires_arc = true
Expand Down
2 changes: 2 additions & 0 deletions ARoute/Classes/Private/Configuration/ARouteConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@
@interface ARouteConfiguration : NSObject

@property (strong, nonatomic, nonnull) NSString *separator;
@property (strong, nonatomic, nonnull) NSString *castingSeparator;
@property (assign, nonatomic) BOOL animate;

@end
9 changes: 9 additions & 0 deletions ARoute/Classes/Private/Configuration/ARouteConfiguration.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,13 @@ - (NSString *)separator
return _separator;
}

- (NSString *)castingSeparator
{
if (!_castingSeparator) {
_castingSeparator = @"|";
}

return _castingSeparator;
}

@end
4 changes: 2 additions & 2 deletions ARoute/Classes/Private/Registration/ARouteRegistration.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
@property (strong, nonatomic, nonnull) ARouteRegistrationConfiguration *registrationConfiguration;
@property (strong, nonatomic, nonnull, readonly) NSArray <ARouteRegistrationItem *> *items;

+ (nonnull instancetype)routeRegistrationWithRouter:(nonnull ARoute *)router routes:(nonnull NSDictionary <NSString*,Class> *)routes routeName:(nullable NSString *)routeName;
+ (nonnull instancetype)routeRegistrationWithRouter:(nonnull ARoute *)router routes:(nonnull NSDictionary <NSString*,Class> *)routes routesGroupName:(nullable NSString *)routesGroupName;
+ (nonnull instancetype)routeRegistrationWithRouter:(nonnull ARoute *)router routes:(nonnull NSDictionary <id,Class> *)routes routeName:(nullable NSString *)routeName;
+ (nonnull instancetype)routeRegistrationWithRouter:(nonnull ARoute *)router routes:(nonnull NSDictionary <id,Class> *)routes routesGroupName:(nullable NSString *)routesGroupName;

@end
35 changes: 31 additions & 4 deletions ARoute/Classes/Private/Registration/ARouteRegistration.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,22 @@ @interface ARouteRegistration ()

@implementation ARouteRegistration

+ (instancetype)routeRegistrationWithRouter:(ARoute *)router routes:(nonnull NSDictionary<NSString *,id> *)routes routeName:(nullable NSString *)routeName
+ (instancetype)routeRegistrationWithRouter:(ARoute *)router routes:(nonnull NSDictionary<id,id> *)routes routeName:(nullable NSString *)routeName
{
ARouteRegistration *routeRegistration = [ARouteRegistration new];
routeRegistration.router = router;

ARouteRegistrationItem *item = [ARouteRegistrationItem new];

NSString *route = routes.allKeys.firstObject;
NSString *route;
id routeObject = routes.allKeys.firstObject;

if ([routeObject isKindOfClass:[NSString class]]) {
route = routeObject;
} else if ([routeObject isKindOfClass:[NSURL class]]) {
route = ((NSURL *)routeObject).absoluteString;
}

id value = routes.allValues.firstObject;

if (object_isClass(value)) {
Expand All @@ -42,13 +50,14 @@ + (instancetype)routeRegistrationWithRouter:(ARoute *)router routes:(nonnull NSD
item.route = route;
item.type = ARouteRegistrationItemTypeNamedRoute;
item.separator = routeRegistration.separator;
item.castingSeparator = routeRegistration.castingSeparator;

routeRegistration.items = @[item];

return routeRegistration;
}

+ (instancetype)routeRegistrationWithRouter:(ARoute *)router routes:(NSDictionary<NSString *,id> *)routes routesGroupName:(NSString *)routesGroupName
+ (instancetype)routeRegistrationWithRouter:(ARoute *)router routes:(NSDictionary<id,id> *)routes routesGroupName:(NSString *)routesGroupName
{
ARouteRegistration *routeRegistration = [ARouteRegistration new];
routeRegistration.router = router;
Expand All @@ -69,6 +78,7 @@ + (instancetype)routeRegistrationWithRouter:(ARoute *)router routes:(NSDictionar
item.route = route;
item.type = ARouteRegistrationItemTypeNamedRoute;
item.separator = routeRegistration.separator;
item.castingSeparator = routeRegistration.castingSeparator;

[items addObject:item];
}];
Expand Down Expand Up @@ -103,6 +113,14 @@ - (instancetype)embedInTabBarController
return self;
}

- (instancetype)embedIn:(__kindof UIViewController<AEmbeddable> *(^)(ARouteResponse * _Nonnull))embeddingViewController
{
[self.items enumerateObjectsUsingBlock:^(ARouteRegistrationItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
obj.embeddingType = ARouteEmbeddingTypeCustomViewController;
}];
return self;
}

- (id<ARouteRegistrationExecutable,ARouteRegistrationConfigurable,ARouteRegistrationProtectable>)separator:(NSString * _Nonnull (^)())separator
{
if (separator) {
Expand Down Expand Up @@ -139,7 +157,7 @@ - (instancetype)embedInTabBarController
return self;
}

- (id <ARouteRegistrationExecutable, ARouteRegistrationConfigurable>)protect:(BOOL (^)(ARouteResponse * _Nonnull))protect
- (id <ARouteRegistrationExecutable, ARouteRegistrationConfigurable>)protect:(BOOL (^)(ARouteResponse * _Nonnull, NSError * _Nullable __autoreleasing * _Nullable))protect
{
if (protect) {
self.registrationConfiguration.protectBlock = protect;
Expand Down Expand Up @@ -172,6 +190,15 @@ - (NSString *)separator
return _separator;
}

- (NSString *)castingSeparator
{
if (!_castingSeparator) {
_castingSeparator = self.router.configuration.castingSeparator;
}

return _castingSeparator;
}

- (ARouteRegistrationConfiguration *)registrationConfiguration
{
if (!_registrationConfiguration) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

@interface ARouteRegistrationConfiguration : NSObject

@property (strong, nonatomic, nullable) BOOL (^protectBlock)(ARouteResponse * _Nonnull routeResponse);
@property (strong, nonatomic, nullable) BOOL (^protectBlock)(ARouteResponse * _Nonnull routeResponse, NSError * __autoreleasing _Nullable * _Nullable errorPtr);
@property (strong, nonatomic, nullable) NSDictionary <id, id> * _Nullable(^parametersBlock)();

@end
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ typedef NS_ENUM(NSInteger, ARouteRegistrationItemType) {
};

typedef NS_ENUM(NSInteger, ARouteEmbeddingType) {
ARouteItemEmbeddingTypeDoNotEmbed,
ARouteEmbeddingTypeNotDefined,
ARouteEmbeddingTypeDoNotEmbed,
ARouteEmbeddingTypeNavigationController,
ARouteEmbeddingTypeTabBarController
ARouteEmbeddingTypeTabBarController,
ARouteEmbeddingTypeCustomViewController
};

@interface ARouteRegistrationItem : NSObject
Expand All @@ -28,7 +30,7 @@ typedef NS_ENUM(NSInteger, ARouteEmbeddingType) {
@property (strong, nonatomic, nonnull) NSString *routeName;
@property (strong, nonatomic, nonnull) Class destinationViewControllerClass;
@property (strong, nonatomic, nonnull) void (^destinationCallback)(ARouteResponse * _Nonnull routeResponse);
@property (strong, nonatomic, nonnull) BOOL(^protectBlock)(ARouteResponse * _Nonnull routeResponse);
@property (strong, nonatomic, nonnull) BOOL (^protectBlock)(ARouteResponse * _Nonnull routeResponse, NSError * __autoreleasing _Nullable * _Nullable errorPtr);
@property (strong, nonatomic, nullable) NSDictionary <id, id> * _Nullable(^parametersBlock)();
@property (strong, nonatomic, nonnull) NSString *separator;
@property (strong, nonatomic, nonnull) NSString *castingSeparator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- (void)storeRouteRegistration:(nonnull ARouteRegistration *)routeRegistration;
- (nullable ARouteRegistrationStorageResult *)routeRegistrationResultForRoute:(nonnull NSString *)route router:(nonnull ARoute *)router;
- (nullable ARouteRegistrationStorageResult *)routeRegistrationResultForRouteName:(nonnull NSString *)routeName router:(nonnull ARoute *)router;
- (nullable ARouteRegistrationStorageResult *)routeRegistrationResultForURL:(nonnull NSURL *)URL router:(nonnull ARoute *)router;
- (void)purgeRouteRegistrations;

@end
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,20 @@ - (ARouteRegistrationStorageResult *)routeRegistrationResultForRouteName:(NSStri
return result;
}

- (ARouteRegistrationStorageResult *)routeRegistrationResultForURL:(NSURL *)URL router:(ARoute *)router
{
NSDictionary *routeParameters;

ARouteRegistrationItem *item = [self routeRegistrationItemForCalledRoute:URL.absoluteString routerName:router.name routeName:nil routeParameters:&routeParameters];

ARouteRegistrationStorageResult *result = [ARouteRegistrationStorageResult new];

result.routeRegistrationItem = item;
result.routeParameters = routeParameters.count ? routeParameters : nil;

return result;
}

- (void)purgeRouteRegistrations
{
[self.routeRegistrationItems removeAllObjects];
Expand All @@ -86,8 +100,8 @@ - (nullable ARouteRegistrationItem *)routeRegistrationItemForCalledRoute:(NSStri

NSDictionary *routeParametersObject;
BOOL routersAreEqual = [obj.router.name isEqualToString:routerName];

BOOL proceed = [self definedRoute:definedRoute isEqualToRoute:calledRoute placeholder:obj.separator routeParameters:&routeParametersObject] && routersAreEqual;
BOOL routesAreEqual = [self definedRoute:definedRoute isEqualToRoute:calledRoute placeholder:obj.separator routeParameters:&routeParametersObject];
BOOL proceed = routesAreEqual && routersAreEqual;

if (proceed) {
routeRegistrationItem = obj;
Expand All @@ -112,16 +126,22 @@ - (BOOL)definedRoute:(NSString *)definedRoute isEqualToRoute:(NSString *)route p

NSArray *routeParameterNames = [self paramNamesForDefinedRoute:definedRoute placeholderComponents:placeholderComponents];

NSString *routeCandidateRegexPattern = [definedRoute copy];
__block NSString *routeCandidateRegexPattern = definedRoute;
NSString *allCharactersRegexPattern = @"([^/]*)";

BOOL matches = NO;

if (routeParameterNames.count) {
for (NSString *paramName in routeParameterNames) {
NSString *uuid = [[NSUUID UUID].UUIDString stringByReplacingOccurrencesOfString:@"-" withString:@""];

[routeParameterNames enumerateObjectsUsingBlock:^(NSString *paramName, NSUInteger idx, BOOL * _Nonnull stop) {
NSString *wrappedParam = [NSString stringWithFormat:@"%@%@%@", placeholderComponents.firstObject, paramName, placeholderComponents.lastObject];
routeCandidateRegexPattern = [routeCandidateRegexPattern stringByReplacingOccurrencesOfString:wrappedParam withString:allCharactersRegexPattern];
}
routeCandidateRegexPattern = [routeCandidateRegexPattern stringByReplacingOccurrencesOfString:wrappedParam withString:uuid];
}];
routeCandidateRegexPattern = [NSRegularExpression escapedPatternForString:routeCandidateRegexPattern];
[routeParameterNames enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
routeCandidateRegexPattern = [routeCandidateRegexPattern stringByReplacingOccurrencesOfString:uuid withString:allCharactersRegexPattern];
}];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", routeCandidateRegexPattern];
matches = [predicate evaluateWithObject:route];
Expand Down
11 changes: 10 additions & 1 deletion ARoute/Classes/Private/Request/ARouteRequest.m
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ + (instancetype)routeRequestWithRouter:(ARoute *)router URL:(nonnull __kindof NS

#pragma mark - ARouteRequestProtectable

- (id<ARouteRequestInitiable,ARouteRequestExecutable,ARouteRequestEmbeddable,ARouteRequestConfigurable>)protect:(BOOL (^)(ARouteResponse *))protect
- (id<ARouteRequestInitiable,ARouteRequestExecutable,ARouteRequestEmbeddable,ARouteRequestConfigurable>)protect:(BOOL (^)(ARouteResponse * _Nonnull, NSError * _Nullable __autoreleasing * _Nullable))protect
{
if (protect) {
self.configuration.protectBlock = protect;
Expand Down Expand Up @@ -141,6 +141,15 @@ + (instancetype)routeRequestWithRouter:(ARoute *)router URL:(nonnull __kindof NS
return self;
}

- (id<ARouteRequestExecutable,ARouteRequestConfigurable>)failure:(void (^)(ARouteResponse * _Nonnull, NSError * _Nullable))failure
{
if (failure) {
self.configuration.failureBlock = failure;
}

return self;
}

- (id<ARouteRequestInitiable,ARouteRequestExecutable,ARouteRequestProtectable,ARouteRequestConfigurable>)transitioningDelegate:(id<UIViewControllerTransitioningDelegate> _Nullable (^)())transitioningDelegate
{
if (transitioningDelegate) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
@property (strong, nonatomic, nullable) NSArray * _Nonnull(^ instantiationArgumentsBlock)(ARouteResponse * _Nonnull);
@property (strong, nonatomic, nullable) UIViewController * _Nullable (^embeddingViewControllerBlock)();
@property (strong, nonatomic, nullable) void (^completionBlock)(ARouteResponse * _Nonnull);
@property (strong, nonatomic, nullable) void (^failureBlock)(ARouteResponse * _Nonnull, NSError * _Nullable error);
@property (strong, nonatomic, nullable) BOOL (^animatedBlock)();
@property (strong, nonatomic, nullable) BOOL (^protectBlock)(ARouteResponse * _Nonnull routeResponse);
@property (strong, nonatomic, nullable) BOOL (^protectBlock)(ARouteResponse * _Nonnull routeResponse, NSError * __autoreleasing _Nullable * _Nullable errorPtr);
@property (strong, nonatomic, nullable) NSDictionary <id, id> * _Nullable(^parametersBlock)();
@property (strong, nonatomic, nullable) id <UIViewControllerTransitioningDelegate> _Nullable(^transitioningDelegateBlock)();
@property (assign, nonatomic) ARouteEmbeddingType embeddingType;
Expand Down
43 changes: 31 additions & 12 deletions ARoute/Classes/Private/RequestExecutor/ARouteRequestExecutor.m
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,15 @@ - (void)executeRouteRequest:(ARouteRequest *)routeRequest routeResponse:(void (^
BOOL animated;
UIViewController *presentingViewController = [self viewControllerForRouteRequest:routeRequest routeResponse:&routeResponse animated:&animated];

[[UIViewController visibleViewController:nil] presentViewController:presentingViewController animated:animated completion:^{
if (routeRequest.configuration.completionBlock) {
routeRequest.configuration.completionBlock(routeResponse);
}
}];
if (routeResponseCallback) {
if (presentingViewController) {
[[UIViewController visibleViewController:nil] presentViewController:presentingViewController animated:animated completion:^{
if (routeRequest.configuration.completionBlock) {
routeRequest.configuration.completionBlock(routeResponse);
}
}];
}

if (routeResponse && routeResponseCallback) {
routeResponseCallback(routeResponse);
}
}
Expand All @@ -69,22 +72,24 @@ - (UIViewController *)viewControllerForRouteRequest:(ARouteRequest *)routeReques

- (UIViewController *)viewControllerForRouteRequest:(ARouteRequest *)routeRequest routeResponse:(ARouteResponse * __autoreleasing *)routeResponsePtr animated:(BOOL*)animatedPtr
{
NSError *errorPtr;
ARouteResponse *response = [ARouteResponse new];
__kindof UIViewController *destinationViewController;
__kindof UIViewController *embeddingViewController;

// preparing params
Class destinationViewControllerClass;
void (^callbackBlock)(ARouteResponse *);
BOOL animated = routeRequest.configuration.animatedBlock ? routeRequest.configuration.animatedBlock() : NO;
BOOL animated = routeRequest.configuration.animatedBlock ? routeRequest.configuration.animatedBlock() : routeRequest.router.configuration.animate;
response.parameters = routeRequest.configuration.parametersBlock ? routeRequest.configuration.parametersBlock() : nil;

NSString *castingSeparator;
NSDictionary *routeParameters;
NSDictionary *registrationParameters;

BOOL (^protectBlock)(ARouteResponse *);
ARouteEmbeddingType embeddingType = 0;
BOOL (^protectBlock)(ARouteResponse * _Nonnull routeResponse, NSError * __autoreleasing _Nullable * _Nullable errorPtr);
ARouteEmbeddingType embeddingType = ARouteEmbeddingTypeNotDefined;

NSArray *previousViewControllers;

ARoute *router = routeRequest.router;
Expand Down Expand Up @@ -122,7 +127,15 @@ - (UIViewController *)viewControllerForRouteRequest:(ARouteRequest *)routeReques
break;
}
case ARouteRequestTypeURL: {

ARouteRegistrationStorageResult *result = [self.routeRegistrationStorage routeRegistrationResultForURL:routeRequest.URL router:router];
destinationViewControllerClass = result.routeRegistrationItem.destinationViewControllerClass;
callbackBlock = result.routeRegistrationItem.destinationCallback;
routeParameters = result.routeParameters;
protectBlock = result.routeRegistrationItem.protectBlock;
castingSeparator = result.routeRegistrationItem.castingSeparator;
registrationParameters = result.routeRegistrationItem.parametersBlock ? result.routeRegistrationItem.parametersBlock() : nil;
embeddingType = result.routeRegistrationItem.embeddingType;
previousViewControllers = result.routeRegistrationItem.previousViewControllersBlock ? result.routeRegistrationItem.previousViewControllersBlock(response) : nil;
break;
}
default:
Expand All @@ -145,11 +158,14 @@ - (UIViewController *)viewControllerForRouteRequest:(ARouteRequest *)routeReques
}

if (protectBlock) {
proceed = !protectBlock(response);
proceed = !protectBlock(response, &errorPtr);
}

proceed = proceed && errorPtr == nil;

if (!proceed) {
self.classPointer = nil;
routeRequest.configuration.failureBlock(response, errorPtr);
return nil;
}

Expand All @@ -175,7 +191,10 @@ - (UIViewController *)viewControllerForRouteRequest:(ARouteRequest *)routeReques
if (routeRequest.configuration.embeddingViewControllerBlock) {
embeddingViewController = routeRequest.configuration.embeddingViewControllerBlock();
} else {
embeddingType = routeRequest.configuration.embeddingType;
if (routeRequest.configuration.embeddingType != ARouteEmbeddingTypeNotDefined) {
embeddingType = routeRequest.configuration.embeddingType;
}

if (routeRequest.configuration.previousViewControllersBlock) {
previousViewControllers = routeRequest.configuration.previousViewControllersBlock(response);
}
Expand Down
2 changes: 2 additions & 0 deletions ARoute/Classes/Public/ARoute.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
- (nonnull id <ARouteRegistrationInitiable, ARouteRegistrationExecutable, ARouteRegistrationProtectable, ARouteRegistrationConfigurable>)registerRoutes:(nonnull NSDictionary <NSString*, id> *)routes;
- (nonnull id <ARouteRegistrationInitiable, ARouteRegistrationExecutable, ARouteRegistrationProtectable, ARouteRegistrationConfigurable>)registerRoute:(nonnull NSDictionary <NSString*, id> *)route withName:(nonnull NSString *)routeName;
- (nonnull id <ARouteRegistrationInitiable, ARouteRegistrationExecutable, ARouteRegistrationProtectable, ARouteRegistrationConfigurable>)registerRoutes:(nonnull NSDictionary <NSString*, id> *)routes withGroupName:(nonnull NSString *)groupName;
- (nonnull id <ARouteRegistrationInitiable, ARouteRegistrationExecutable, ARouteRegistrationProtectable, ARouteRegistrationConfigurable>)registerURLs:(nonnull NSDictionary <NSURL*, id> *)routes;

- (void)clearAllRouteRegistrations;

@end
6 changes: 6 additions & 0 deletions ARoute/Classes/Public/ARoute.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

#import "ARoute.h"
#import <objc/runtime.h>

@class ARouteRequest;

Expand Down Expand Up @@ -92,6 +93,11 @@ + (ARouteConfiguration *)configuration
return [ARouteRegistration routeRegistrationWithRouter:self routes:routes routesGroupName:groupName];
}

- (id<ARouteRegistrationInitiable,ARouteRegistrationExecutable,ARouteRegistrationProtectable,ARouteRegistrationConfigurable>)registerURLs:(NSDictionary<NSURL *,id> *)routes
{
return [ARouteRegistration routeRegistrationWithRouter:self routes:routes routesGroupName:nil];
}

- (void)clearAllRouteRegistrations
{
[self.storage purgeRouteRegistrations];
Expand Down
Loading

0 comments on commit 3c30d01

Please sign in to comment.