├── .gitignore ├── .travis.yml ├── MobileDeepLinking-iOS ├── MDLConfig.h ├── MDLConfig.m ├── MDLConstants.h ├── MDLConstants.m ├── MDLDeeplinkMatcher.h ├── MDLDeeplinkMatcher.m ├── MDLError.h ├── MDLError.m ├── MDLHandlerExecutor.h ├── MDLHandlerExecutor.m ├── MDLViewBuilder.h ├── MDLViewBuilder.m ├── MDLViewNavigator.h ├── MDLViewNavigator.m ├── MobileDeepLinking-Prefix.pch ├── MobileDeepLinking.h ├── MobileDeepLinking.m └── MobileDeepLinking_Private.h ├── MobileDeepLinking-iOSTests ├── ExecuteHandlersTest.m ├── GetRequiredRouteParameterValuesTest.m ├── MatchPathParameterTest.m ├── MatchQueryParameterTest.m ├── MobileDeepLinkingTests-Info.plist ├── RegexValidationTest.m ├── TrimDeeplinkTest.m └── en.lproj │ └── InfoPlist.strings ├── MobileDeepLinking.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ ├── Framework.xcscheme │ ├── MobileDeepLinking-iOS.xcscheme │ └── Run Tests.xcscheme ├── MobileDeepLinkingDemo ├── MobileDeepLinkingDemo.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── MobileDeepLinkingDemo.xcscheme ├── MobileDeepLinkingDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ │ ├── Main_iPad.storyboard │ │ └── Main_iPhone.storyboard │ ├── DataViewController.h │ ├── DataViewController.m │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── LaunchImage.launchimage │ │ │ └── Contents.json │ ├── MobileDeepLinkingConfig.json │ ├── MobileDeepLinkingDemo-Info.plist │ ├── MobileDeepLinkingDemo-Prefix.pch │ ├── NonIBViewController.h │ ├── NonIBViewController.m │ ├── StoryBoardViewController.h │ ├── StoryBoardViewController.m │ ├── ViewControllerWithNib.h │ ├── ViewControllerWithNib.m │ ├── ViewControllerWithNib.xib │ ├── en.lproj │ │ └── InfoPlist.strings │ └── main.m └── MobileDeepLinkingDemoTests │ ├── MobileDeepLinkingDemoTests-Info.plist │ ├── MobileDeepLinkingDemoTests.m │ └── en.lproj │ └── InfoPlist.strings ├── Podfile ├── Podfile.lock ├── README.md └── releases ├── 0.1.0 └── MobileDeepLinking.framework │ ├── Headers │ ├── MobileDeepLinking │ └── Versions │ ├── A │ ├── Headers │ │ └── MobileDeepLinking.h │ └── MobileDeepLinking │ └── Current ├── 0.1.1 └── MobileDeepLinking.framework │ ├── Headers │ ├── MobileDeepLinking │ └── Versions │ ├── A │ ├── Headers │ │ └── MobileDeepLinking.h │ └── MobileDeepLinking │ └── Current └── 0.2.0 └── MobileDeepLinking.framework ├── Headers ├── MobileDeepLinking └── Versions ├── A ├── Headers │ └── MobileDeepLinking.h └── MobileDeepLinking └── Current /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | *.xcworkspace 13 | !default.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .idea/ 19 | 20 | # CocoaPods 21 | Pods/ 22 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | before_install: gem install cocoapods 3 | xcode_workspace: MobileDeepLinking.xcworkspace 4 | xcode_scheme: MobileDeepLinking-iOS 5 | xcode_sdk: iphonesimulator 6 | -------------------------------------------------------------------------------- /MobileDeepLinking-iOS/MDLConfig.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | 26 | @interface MDLConfig : NSObject 27 | { 28 | BOOL _logging; 29 | NSDictionary *_storyboard; 30 | NSDictionary * _routes; 31 | NSDictionary * _defaultRoute; 32 | } 33 | 34 | - (id)initConfiguration; 35 | 36 | @property (nonatomic, assign) BOOL logging; 37 | @property (nonatomic, retain) NSDictionary *storyboard; 38 | @property (nonatomic, retain) NSDictionary * routes; 39 | @property (nonatomic, retain) NSDictionary * defaultRoute; 40 | 41 | @end -------------------------------------------------------------------------------- /MobileDeepLinking-iOS/MDLConfig.m: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "MDLConfig.h" 24 | #import "MobileDeepLinking.h" 25 | 26 | 27 | @implementation MDLConfig 28 | { 29 | } 30 | 31 | @synthesize logging = _logging; 32 | @synthesize storyboard = _storyboard; 33 | @synthesize routes = _routes; 34 | @synthesize defaultRoute = _defaultRoute; 35 | 36 | - (id)initConfiguration 37 | { 38 | self = [super init]; 39 | 40 | if (self) 41 | { 42 | NSError *error = nil; 43 | NSString *configFilePath = [[NSBundle bundleForClass:[self class]] pathForResource:MOBILEDEEPLINKING_CONFIG_NAME ofType:@"json"]; 44 | if (configFilePath == nil) 45 | { 46 | // Fall back to main bundle if not found in class / framework bundle. 47 | configFilePath = [[NSBundle mainBundle] pathForResource:MOBILEDEEPLINKING_CONFIG_NAME ofType:@"json"]; 48 | } 49 | NSData *configData = [[NSFileManager defaultManager] contentsAtPath:configFilePath]; 50 | NSDictionary *config = [NSJSONSerialization JSONObjectWithData:configData options:0 error:&error]; 51 | if (config == nil) 52 | { 53 | NSLog(@"MobileDeepLinking configuration file error: %@", error); 54 | return nil; 55 | } 56 | 57 | _logging = ([[config objectForKey:LOGGING_JSON_NAME] isEqualToString:@"true"]); 58 | _routes = [config objectForKey:ROUTES_JSON_NAME]; 59 | _storyboard = [config objectForKey:STORYBOARD_JSON_NAME]; 60 | _defaultRoute = [config objectForKey:DEFAULT_ROUTE_JSON_NAME]; 61 | } 62 | return self; 63 | } 64 | 65 | @end -------------------------------------------------------------------------------- /MobileDeepLinking-iOS/MDLConstants.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | 26 | @interface MDLConstants : NSObject 27 | 28 | #define MOBILEDEEPLINKING_CONFIG_NAME @"MobileDeepLinkingConfig" 29 | #define ROUTES_JSON_NAME @"routes" 30 | #define STORYBOARD_JSON_NAME @"storyboard" 31 | #define HANDLERS_JSON_NAME @"handlers" 32 | #define CLASS_JSON_NAME @"class" 33 | #define IDENTIFIER_JSON_NAME @"identifier" 34 | #define LOGGING_JSON_NAME @"logging" 35 | #define DEFAULT_ROUTE_JSON_NAME @"defaultRoute" 36 | #define ROUTE_PARAMS_JSON_NAME @"routeParameters" 37 | #define REQUIRED_JSON_NAME @"required" 38 | #define REGEX_JSON_NAME @"regex" 39 | #define STORYBOARD_IPHONE_NAME @"iPhone" 40 | #define STORYBOARD_IPAD_NAME @"iPad" 41 | 42 | @end -------------------------------------------------------------------------------- /MobileDeepLinking-iOS/MDLConstants.m: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "MDLConstants.h" 24 | 25 | 26 | @implementation MDLConstants 27 | 28 | @end -------------------------------------------------------------------------------- /MobileDeepLinking-iOS/MDLDeeplinkMatcher.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | 26 | @interface MDLDeeplinkMatcher : NSObject 27 | 28 | + (BOOL)matchDeeplink:(NSString *)route routeOptions:(NSDictionary *)routeOptions deeplink:(NSURL *)deeplink results:(NSMutableDictionary *)results error:(NSError **)error; 29 | 30 | + (BOOL)matchPathParameters:(NSString *)route routeOptions:(NSDictionary *)routeOptions deeplink:(NSURL *)deeplink results:(NSMutableDictionary *)results error:(NSError **)error; 31 | 32 | + (BOOL)matchQueryParameters:(NSString *)queryString routeOptions:(NSDictionary *)routeOptions result:(NSMutableDictionary *)routeParameterValues error:(NSError **)error; 33 | 34 | + (BOOL)checkForRequiredRouteParameters:(NSDictionary *)routeOptions extractedResults:(NSDictionary *)results error:(NSError **)error; 35 | 36 | + (NSMutableDictionary *)getRequiredRouteParameterValues:(NSDictionary *)routeOptions; 37 | 38 | + (BOOL)validateRouteComponent:(NSString *)name value:(NSString *)value routeOptions:(NSDictionary *)routeOptions; 39 | 40 | 41 | @end -------------------------------------------------------------------------------- /MobileDeepLinking-iOS/MDLDeeplinkMatcher.m: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "MDLDeeplinkMatcher.h" 24 | #import "MDLError.h" 25 | 26 | 27 | @implementation MDLDeeplinkMatcher 28 | 29 | /** 30 | * Match the incoming deeplink on the route options in the JSON. If path or query parameters are encountered, run validation and place 31 | * the result into the NSDictionary * results. 32 | */ 33 | + (BOOL)matchDeeplink:(NSString *)route routeOptions:(NSDictionary *)routeOptions deeplink:(NSURL *)deeplink results:(NSMutableDictionary *)results error:(NSError **)error 34 | { 35 | return [self matchPathParameters:route routeOptions:routeOptions deeplink:deeplink results:results error:error] 36 | && [self matchQueryParameters:[deeplink query] routeOptions:routeOptions result:results error:error] 37 | && [self checkForRequiredRouteParameters:routeOptions extractedResults:results error:error]; 38 | } 39 | 40 | /** 41 | * Match incoming deeplink's path parameters. If wildcard (:path) is encountered, run validation on it and place 42 | * the result into the NSDictionary * results. 43 | */ 44 | + (BOOL)matchPathParameters:(NSString *)route routeOptions:(NSDictionary *)routeOptions deeplink:(NSURL *)deeplink results:(NSMutableDictionary *)results error:(NSError **)error 45 | { 46 | // routeDefinition: host/routeDefinition/path1?query=string&query2=string 47 | NSMutableArray *routeComponents = [NSMutableArray arrayWithArray:[route componentsSeparatedByString:@"/"]]; 48 | NSMutableArray *deeplinkComponents = [NSMutableArray arrayWithArray:[[deeplink path] componentsSeparatedByString:@"/"]]; 49 | 50 | // [url path] returns /somePath, so componentsSeparatedByString will return @"" as the first element. 51 | [deeplinkComponents removeObject:@""]; 52 | 53 | // if route starts with a host. 54 | if (![route hasPrefix:@"/"]) 55 | { 56 | NSString *host = [deeplink host]; 57 | if (![[routeComponents objectAtIndex:0] isEqualToString:host]) 58 | { 59 | return NO; 60 | } 61 | [routeComponents removeObjectAtIndex:0]; 62 | } 63 | 64 | if ([routeComponents count] != [deeplinkComponents count]) 65 | { 66 | return NO; 67 | } 68 | 69 | NSString *routeComponent = nil; 70 | NSString *deeplinkComponent = nil; 71 | for (int i = 0; i < [routeComponents count]; i++) 72 | { 73 | routeComponent = routeComponents[i]; 74 | deeplinkComponent = deeplinkComponents[i]; 75 | if (![routeComponent isEqualToString:deeplinkComponent]) 76 | { 77 | if ([routeComponent hasPrefix:@":"]) 78 | { 79 | NSString *routeComponentName = [routeComponent substringFromIndex:1]; 80 | BOOL validationSuccess = [self validateRouteComponent:routeComponentName value:deeplinkComponent routeOptions:routeOptions]; 81 | if (validationSuccess) 82 | { 83 | [results setValue:deeplinkComponent forKey:routeComponentName]; 84 | } 85 | else 86 | { 87 | [MDLError setError:error withMessage:[NSString stringWithFormat:@"Validation for %@ failed.", routeComponentName]]; 88 | return NO; 89 | } 90 | } 91 | else 92 | { 93 | return NO; 94 | } 95 | } 96 | } 97 | 98 | return YES; 99 | } 100 | 101 | 102 | /** 103 | * Checks route options (which define accepted query parameters) against incoming query parameters. 104 | * 105 | * RESTRICTIONS: 106 | * Query Parameter Names may not be repeated. If they are, we will only get the last one. 107 | * There should not be a query parameter with the same name as the path parameter. 108 | * 109 | * Note, this does handle escaped query parameters. 110 | * 111 | * Precondition: queryString should not start with ? 112 | */ 113 | + (BOOL)matchQueryParameters:(NSString *)queryString routeOptions:(NSDictionary *)routeOptions result:(NSMutableDictionary *)routeParameterValues error:(NSError **)error 114 | { 115 | NSDictionary *routeParameters = [routeOptions objectForKey:ROUTE_PARAMS_JSON_NAME]; 116 | NSArray *queryPairs = [queryString componentsSeparatedByString:@"&"]; 117 | for (NSString *keyValuePair in queryPairs) 118 | { 119 | NSArray *nameAndValue = [keyValuePair componentsSeparatedByString:@"="]; 120 | if ([nameAndValue count] == 2) 121 | { 122 | NSString *name = [[nameAndValue objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 123 | // only accept query parameters that have been specified in route parameters 124 | if ([[routeParameters allKeys] containsObject:name] == NO) 125 | { 126 | continue; 127 | } 128 | 129 | NSString *value = [[nameAndValue objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 130 | 131 | if ([self validateRouteComponent:name value:value routeOptions:routeOptions] == YES) 132 | { 133 | [routeParameterValues setValue:value forKey:name]; 134 | } 135 | else 136 | { 137 | [MDLError setError:error withMessage:@"Query Parameter Regex checking failed."]; 138 | return NO; 139 | } 140 | } 141 | } 142 | return YES; 143 | } 144 | 145 | + (BOOL)checkForRequiredRouteParameters:(NSDictionary *)routeOptions extractedResults:(NSDictionary *)results error:(NSError **)error 146 | { 147 | NSDictionary *requiredRouteParameterValues = [self getRequiredRouteParameterValues:routeOptions]; 148 | for (NSString *requiredValueKey in requiredRouteParameterValues) 149 | { 150 | if ([results objectForKey:requiredValueKey] == nil) 151 | { 152 | [MDLError setError:error withMessage:[NSString stringWithFormat:@"%@ route parameter is missing.", requiredValueKey]]; 153 | return NO; 154 | } 155 | } 156 | return YES; 157 | } 158 | 159 | + (NSMutableDictionary *)getRequiredRouteParameterValues:(NSDictionary *)routeOptions 160 | { 161 | NSMutableDictionary *requiredRouteParameters = [[NSMutableDictionary alloc] init]; 162 | NSDictionary *routeParameters = [routeOptions objectForKey:ROUTE_PARAMS_JSON_NAME]; 163 | for (id routeParameter in routeParameters) 164 | { 165 | NSDictionary *routeParameterOptions = [routeParameters objectForKey:routeParameter]; 166 | if ([[routeParameterOptions objectForKey:REQUIRED_JSON_NAME] isEqual:@"true"]) 167 | { 168 | [requiredRouteParameters setValue:@YES forKey:routeParameter]; 169 | } 170 | } 171 | 172 | return requiredRouteParameters; 173 | } 174 | 175 | 176 | /** 177 | * Validate a route component (path or query parameter) against regular expression defined in json. 178 | */ 179 | + (BOOL)validateRouteComponent:(NSString *)name value:(NSString *)value routeOptions:(NSDictionary *)routeOptions; 180 | { 181 | NSDictionary *routeParameters = [routeOptions objectForKey:ROUTE_PARAMS_JSON_NAME]; 182 | NSDictionary *pathComponentParameters = [routeParameters objectForKey:name]; 183 | NSString *regexString = [pathComponentParameters objectForKey:REGEX_JSON_NAME]; 184 | if (regexString != nil) 185 | { 186 | NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regexString options:0 error:nil]; 187 | 188 | NSArray *matches = [regex matchesInString:value options:0 range:NSMakeRange(0, [value length])]; 189 | return ([matches count] == 1); 190 | } 191 | return YES; 192 | } 193 | 194 | @end -------------------------------------------------------------------------------- /MobileDeepLinking-iOS/MDLError.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | 26 | @interface MDLError : NSObject 27 | 28 | + (void)setError:(NSError **)error withMessage:(NSString *)message; 29 | 30 | @end -------------------------------------------------------------------------------- /MobileDeepLinking-iOS/MDLError.m: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "MDLError.h" 24 | 25 | 26 | @implementation MDLError 27 | 28 | + (void)setError:(NSError **)error withMessage:(NSString *)message 29 | { 30 | if (error) 31 | { 32 | NSDictionary *userInfo = @{ 33 | NSLocalizedDescriptionKey : NSLocalizedString(message, nil) 34 | }; 35 | *error = [NSError errorWithDomain:@"MobileDeepLinkingErrorDomain" 36 | code:-57 37 | userInfo:userInfo]; 38 | } 39 | } 40 | @end -------------------------------------------------------------------------------- /MobileDeepLinking-iOS/MDLHandlerExecutor.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | 26 | @interface MDLHandlerExecutor : NSObject 27 | 28 | + (BOOL)executeHandlers:(NSDictionary *)routeOptions routeParams:(NSDictionary *)routeParams handlers:(NSDictionary *)handlers error:(NSError **)error; 29 | 30 | @end -------------------------------------------------------------------------------- /MobileDeepLinking-iOS/MDLHandlerExecutor.m: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "MDLHandlerExecutor.h" 24 | #import "MDLError.h" 25 | 26 | 27 | @implementation MDLHandlerExecutor 28 | 29 | /** 30 | * Execute registered handlers. Note, modifying the routeParams dictionary in your blocks will persist on any 31 | * subsequent handler execution and upon view instantiation. 32 | */ 33 | + (BOOL)executeHandlers:(NSDictionary *)routeOptions routeParams:(NSDictionary *)routeParams handlers:(NSDictionary *)handlers error:(NSError **)error 34 | { 35 | // Execute Handlers for Route 36 | if ([routeOptions objectForKey:HANDLERS_JSON_NAME] != nil) 37 | { 38 | NSArray *routeHandlers = [routeOptions objectForKey:HANDLERS_JSON_NAME]; 39 | for (int i = 0; i < [routeHandlers count]; i++) 40 | { 41 | if ([handlers objectForKey:routeHandlers[i]] != nil) 42 | { 43 | void(^handlerBlock)(NSDictionary *) = [handlers objectForKey:routeHandlers[i]]; 44 | handlerBlock(routeParams); 45 | } 46 | else 47 | { 48 | [MDLError setError:error withMessage:[NSString stringWithFormat:@"Handler %@ has not been registered with the MobileDeepLinking library.", routeHandlers[i]]]; 49 | return NO; 50 | } 51 | } 52 | } 53 | return YES; 54 | } 55 | 56 | @end -------------------------------------------------------------------------------- /MobileDeepLinking-iOS/MDLViewBuilder.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | #import 25 | 26 | @class MDLConfig; 27 | 28 | 29 | @interface MDLViewBuilder : NSObject 30 | 31 | + (id)buildViewController:(NSDictionary *)routeOptions config:(MDLConfig *)config; 32 | 33 | + (BOOL)displayView:(NSDictionary *)routeOptions routeParams:(NSDictionary *)routeParams config:(MDLConfig *)config error:(NSError **)error; 34 | 35 | + (BOOL)setPropertiesOnViewController:(UIViewController *)viewController routeParams:(NSDictionary *)routeParams config:(MDLConfig *)config; 36 | 37 | @end -------------------------------------------------------------------------------- /MobileDeepLinking-iOS/MDLViewBuilder.m: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "MDLViewBuilder.h" 24 | #import "MDLError.h" 25 | #import "MDLConfig.h" 26 | #import "MDLViewNavigator.h" 27 | 28 | 29 | @implementation MDLViewBuilder 30 | 31 | /** 32 | * Display View based on presence of storyboard, identifier, and class. 33 | */ 34 | + (BOOL)displayView:(NSDictionary *)routeOptions routeParams:(NSDictionary *)routeParams config:(MDLConfig *)config error:(NSError **)error 35 | { 36 | // construct view controller 37 | id newViewController = [self buildViewController:routeOptions config:config]; 38 | if (!newViewController) 39 | { 40 | if (config.logging) 41 | { 42 | NSLog(@"No View Controllers found in route options."); 43 | } 44 | return NO; 45 | } 46 | 47 | BOOL success = [self setPropertiesOnViewController:newViewController routeParams:routeParams config:config]; 48 | if (!success) 49 | { 50 | [MDLError setError:error withMessage:[NSString stringWithFormat:@"Setting properties on %@ failed.", NSStringFromClass([newViewController class])]]; 51 | return NO; 52 | } 53 | 54 | // push view controller 55 | MDLViewNavigator *viewNavigator = [[MDLViewNavigator alloc] initWithRootViewController:[[UIApplication sharedApplication] keyWindow].rootViewController]; 56 | [viewNavigator showViewController:newViewController]; 57 | return YES; 58 | } 59 | 60 | /** 61 | * Depending on the combination of storyboard, identifier, and class, build a view controller. 62 | */ 63 | + (id)buildViewController:(NSDictionary *)routeOptions config:(MDLConfig *)config 64 | { 65 | NSString *storyboardName = [self getStoryboardName:config.storyboard]; 66 | 67 | if ([routeOptions objectForKey:STORYBOARD_JSON_NAME]) 68 | { 69 | storyboardName = [self getStoryboardName:[routeOptions objectForKey:STORYBOARD_JSON_NAME]]; 70 | } 71 | 72 | NSString *identifier = [routeOptions objectForKey:IDENTIFIER_JSON_NAME]; 73 | NSString *class = [routeOptions objectForKey:CLASS_JSON_NAME]; 74 | 75 | if (([storyboardName length] != 0) && ([identifier length] != 0)) 76 | { 77 | if (config.logging) 78 | { 79 | NSLog(@"Routing to %@.", [routeOptions objectForKey:IDENTIFIER_JSON_NAME]); 80 | } 81 | UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil]; 82 | return [storyboard instantiateViewControllerWithIdentifier:[routeOptions objectForKey:IDENTIFIER_JSON_NAME]]; 83 | } 84 | else if (([class length] != 0) && ([identifier length] != 0)) 85 | { 86 | // Create view controller with nib. 87 | if (config.logging) 88 | { 89 | NSLog(@"Routing to %@.", [routeOptions objectForKey:CLASS_JSON_NAME]); 90 | } 91 | return [[NSClassFromString([routeOptions objectForKey:CLASS_JSON_NAME]) alloc] initWithNibName:[routeOptions objectForKey:IDENTIFIER_JSON_NAME] bundle:nil]; 92 | } 93 | else if ([class length] != 0) 94 | { 95 | // Create a old-fashioned view controller without storyboard or nib. 96 | if (config.logging) 97 | { 98 | NSLog(@"Routing to %@.", [routeOptions objectForKey:CLASS_JSON_NAME]); 99 | } 100 | return [[NSClassFromString([routeOptions objectForKey:CLASS_JSON_NAME]) alloc] init]; 101 | } 102 | else 103 | { 104 | return nil; 105 | } 106 | } 107 | 108 | + (NSString *)getStoryboardName:(NSDictionary *)storyboard 109 | { 110 | NSString * storyboardName = nil; 111 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) 112 | { 113 | storyboardName = [storyboard objectForKey:STORYBOARD_IPHONE_NAME]; 114 | } 115 | else 116 | { 117 | storyboardName = [storyboard objectForKey:STORYBOARD_IPAD_NAME]; 118 | 119 | // if ipad storyboard is not defined, fall back to iphone storyboard 120 | if (storyboardName == nil) 121 | { 122 | storyboardName = [storyboard objectForKey:STORYBOARD_IPHONE_NAME]; 123 | } 124 | } 125 | return storyboardName; 126 | } 127 | 128 | + (BOOL)setPropertiesOnViewController:(UIViewController *)viewController routeParams:(NSDictionary *)routeParams config:(MDLConfig *)config 129 | { 130 | for (id routeParam in routeParams) 131 | { 132 | NSError *error = nil; 133 | // Validation follows pattern described here: https://developer.apple.com/library/mac/documentation/cocoa/conceptual/KeyValueCoding/Articles/Validation.html 134 | // User can create custom validators for their properties. If none exist, validateValue will return YES by default. 135 | id valueToValidate = [routeParams objectForKey:routeParam]; 136 | BOOL valid = [viewController validateValue:&valueToValidate forKey:routeParam error:&error]; 137 | if (valid == NO) 138 | { 139 | if (config.logging) 140 | { 141 | NSLog(@"Validation error when setting key:%@. Reason:%@", routeParam, error.localizedDescription); 142 | } 143 | return NO; 144 | } 145 | 146 | @try 147 | { 148 | [viewController setValue:valueToValidate forKey:routeParam]; 149 | } 150 | @catch (NSException *e) 151 | { 152 | if (config.logging) 153 | { 154 | NSLog(@"Unable to set property: %@ on %@.", routeParam, NSStringFromClass([viewController class])); 155 | } 156 | } 157 | } 158 | return YES; 159 | } 160 | 161 | @end -------------------------------------------------------------------------------- /MobileDeepLinking-iOS/MDLViewNavigator.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | 26 | @interface MDLViewNavigator : NSObject 27 | 28 | @property (nonatomic, assign) UIViewController* rootViewController; 29 | 30 | - (id)initWithRootViewController:(UIViewController *)rootViewController; 31 | - (void)showViewController:(UIViewController*)viewController; 32 | 33 | @end -------------------------------------------------------------------------------- /MobileDeepLinking-iOS/MDLViewNavigator.m: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | #import "MDLViewNavigator.h" 25 | 26 | 27 | @implementation MDLViewNavigator 28 | 29 | @synthesize rootViewController = _rootViewController; 30 | 31 | - (id)initWithRootViewController:(UIViewController *)rootViewController 32 | { 33 | self = [super init]; 34 | if (self) 35 | { 36 | _rootViewController = rootViewController; 37 | } 38 | return self; 39 | } 40 | 41 | /** 42 | * Attempts to show view on UINavigationController. Assumes that rootViewController is either UINavigationController or UITabBarView with a child UINavigationController. 43 | * If UINavigationController is not found, replace rootViewController with selected view controller. 44 | */ 45 | - (void)showViewController:(UIViewController*)viewController 46 | { 47 | if ([_rootViewController isKindOfClass:[UINavigationController class]]) 48 | { 49 | [self pushViewControllerOntoRoot:(UINavigationController *) _rootViewController controller:viewController]; 50 | } 51 | else if ([_rootViewController isKindOfClass:[UITabBarController class]]) 52 | { 53 | UITabBarController *tabBarController = (UITabBarController *)_rootViewController; 54 | for (UIViewController *controllerInTabBar in tabBarController.viewControllers) 55 | { 56 | if ([viewController isKindOfClass:[controllerInTabBar class]]) 57 | { 58 | [tabBarController setSelectedViewController:controllerInTabBar]; 59 | return; 60 | } 61 | } 62 | 63 | if ([[tabBarController.viewControllers objectAtIndex:0] isKindOfClass:[UINavigationController class]]) 64 | { 65 | [self pushViewControllerOntoRoot:(UINavigationController *)[tabBarController.viewControllers objectAtIndex:0] controller:viewController]; 66 | [tabBarController setSelectedIndex:0]; 67 | } 68 | } 69 | else 70 | { 71 | [[UIApplication sharedApplication] keyWindow].rootViewController = viewController; 72 | } 73 | } 74 | 75 | - (void) pushViewControllerOntoRoot:(UINavigationController *)navController controller:(UIViewController *)viewController 76 | { 77 | [navController popToRootViewControllerAnimated:NO]; 78 | 79 | if (![viewController isKindOfClass:[navController.viewControllers[0] class]]) 80 | { 81 | [navController pushViewController:viewController animated:YES]; 82 | } 83 | } 84 | 85 | 86 | @end -------------------------------------------------------------------------------- /MobileDeepLinking-iOS/MobileDeepLinking-Prefix.pch: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #ifdef __OBJC__ 24 | 25 | #import 26 | #import "MDLConstants.h" 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /MobileDeepLinking-iOS/MobileDeepLinking.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | #import 25 | 26 | @interface MobileDeepLinking : NSObject 27 | 28 | + (id)sharedInstance; 29 | 30 | - (void)registerHandlerWithName:(NSString *)handlerName handler:(void (^)(NSDictionary *))handlerFunction; 31 | 32 | - (void)routeUsingUrl:(NSURL *)deeplink; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /MobileDeepLinking-iOS/MobileDeepLinking.m: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "MobileDeepLinking.h" 24 | #import "MDLDeeplinkMatcher.h" 25 | #import "MDLHandlerExecutor.h" 26 | #import "MDLViewBuilder.h" 27 | #import "MDLConfig.h" 28 | 29 | @implementation MobileDeepLinking 30 | { 31 | MDLConfig *config; 32 | NSMutableDictionary *handlers; 33 | } 34 | 35 | #pragma mark - Initialization Methods 36 | 37 | + (id)sharedInstance 38 | { 39 | static dispatch_once_t pred; 40 | static MobileDeepLinking *sharedInstance = nil; 41 | dispatch_once(&pred, ^ 42 | { 43 | sharedInstance = [[MobileDeepLinking alloc] init]; 44 | }); 45 | return sharedInstance; 46 | } 47 | 48 | - (id)init 49 | { 50 | self = [super init]; 51 | if (self) 52 | { 53 | config = [[MDLConfig alloc] initConfiguration]; 54 | } 55 | return self; 56 | } 57 | 58 | #pragma mark - Public Methods 59 | 60 | /** 61 | * Register a Custom Handler Function with the MobileDeepLinking library. 62 | * This method should be called in the application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 63 | * function in AppDelegate.m. 64 | * 65 | * @handlerName - name to register handler function under 66 | * @handlerFunction - a block function declaration that takes in a NSDictionary 67 | */ 68 | - (void)registerHandlerWithName:(NSString *)handlerName handler:(void (^)(NSDictionary *))handlerFunction 69 | { 70 | if (handlers == nil) 71 | { 72 | handlers = [[NSMutableDictionary alloc] init]; 73 | } 74 | [handlers setObject:[handlerFunction copy] forKey:handlerName]; 75 | } 76 | 77 | /** 78 | * Route to the appropriate view and/or handler function using the custom url. 79 | * This method should be called in the application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation 80 | * function in AppDelegate.m. 81 | * 82 | * @deeplink - The NSURL that comes in openURL in the above function. 83 | */ 84 | - (void)routeUsingUrl:(NSURL *)deeplink 85 | { 86 | NSError *error = nil; 87 | 88 | // base case 89 | if (([[deeplink host] length] == 0) && 90 | ([[deeplink path] isEqualToString:@"/"] || [[deeplink path] length] == 0)) 91 | { 92 | if (config.logging) 93 | { 94 | NSLog(@"No Routes Match."); 95 | } 96 | [self routeToDefault]; 97 | return; 98 | } 99 | 100 | NSMutableDictionary *routeParameterValues = nil; 101 | for (id route in config.routes) 102 | { 103 | error = nil; 104 | routeParameterValues = [[NSMutableDictionary alloc] init]; 105 | NSDictionary *routeOptions = [config.routes objectForKey:route]; 106 | if ([MDLDeeplinkMatcher matchDeeplink:route routeOptions:routeOptions deeplink:deeplink results:routeParameterValues error:&error]) 107 | { 108 | if (routeParameterValues == nil && error != nil) 109 | { 110 | if (config.logging) 111 | { 112 | NSLog(@"Error Getting routeParameterValues: %@", error.localizedDescription); 113 | } 114 | break; 115 | } 116 | 117 | BOOL success = [self handleRouteWithOptions:routeOptions params:routeParameterValues error:&error]; 118 | if (!success && error != nil) 119 | { 120 | if (config.logging) 121 | { 122 | NSLog(@"Error when handling route: %@", error.localizedDescription); 123 | } 124 | break; 125 | } 126 | return; 127 | } 128 | else 129 | { 130 | if (error != nil && config.logging) 131 | { 132 | NSLog(@"Route did not match: %@", error.localizedDescription); 133 | break; 134 | } 135 | } 136 | } 137 | 138 | // trim deeplink 139 | return [self routeUsingUrl:[self trimDeeplink:deeplink]]; 140 | } 141 | 142 | #pragma mark - Private Helper Methods 143 | 144 | /** 145 | * Executes handlers and displays views. 146 | */ 147 | - (BOOL)handleRouteWithOptions:(NSDictionary *)routeOptions params:(NSDictionary *)routeParams error:(NSError **)error 148 | { 149 | return [MDLHandlerExecutor executeHandlers:routeOptions routeParams:routeParams handlers:handlers error:error] 150 | && [MDLViewBuilder displayView:routeOptions routeParams:routeParams config:config error:error]; 151 | } 152 | 153 | - (void)routeToDefault 154 | { 155 | if (config.logging) 156 | { 157 | NSLog(@"Routing to Default Route."); 158 | } 159 | [self handleRouteWithOptions:config.defaultRoute params:nil error:nil]; 160 | } 161 | 162 | /** 163 | * This method trims off the last path or host component in an NSURL. 164 | */ 165 | - (NSURL *)trimDeeplink:(NSURL *)deeplink 166 | { 167 | NSString *deeplinkHost = [deeplink host]; 168 | NSMutableArray *pathComponents = [NSMutableArray arrayWithArray:[deeplink pathComponents]]; 169 | if ([pathComponents count] == 0) 170 | { 171 | // path is empty - remove host if host exists 172 | if (deeplinkHost) 173 | { 174 | deeplinkHost = nil; 175 | } 176 | } 177 | 178 | for (int i = ((int) [pathComponents count]) - 1; i >= 0; i--) 179 | { 180 | // remove any trailing slashes 181 | if ([pathComponents[i] isEqual:@"/"]) 182 | { 183 | [pathComponents removeObjectAtIndex:i]; 184 | } 185 | else 186 | { 187 | [pathComponents removeObjectAtIndex:i]; 188 | break; 189 | } 190 | } 191 | 192 | NSString *pathString = @""; 193 | // build path string. Start at i = 1 because first element of pathComponents is always / 194 | for (int i = 1; i < [pathComponents count]; i++) 195 | { 196 | pathString = [pathString stringByAppendingString:@"/"]; 197 | pathString = [pathString stringByAppendingString:pathComponents[i]]; 198 | } 199 | 200 | return [[NSURL alloc] initWithString:[NSString stringWithFormat:@"%@://%@%@%@", 201 | [deeplink scheme], 202 | (deeplinkHost) ? deeplinkHost : @"", 203 | pathString, 204 | ([deeplink query]) ? [NSString stringWithFormat:@"?%@", [deeplink query]] : @""]]; 205 | } 206 | 207 | 208 | - (void)dealloc 209 | { 210 | abort(); 211 | } 212 | 213 | 214 | @end 215 | -------------------------------------------------------------------------------- /MobileDeepLinking-iOS/MobileDeepLinking_Private.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | // This is a private interface for unit testing. 24 | 25 | #import "MobileDeepLinking.h" 26 | 27 | @interface MobileDeepLinking () 28 | 29 | - (void)routeToDefault; 30 | 31 | - (BOOL)handleRouteWithOptions:(NSDictionary *)routeOptions params:(NSDictionary *)routeParams error:(NSError **)error; 32 | 33 | - (NSURL *)trimDeeplink:(NSURL *)deeplink; 34 | 35 | @end -------------------------------------------------------------------------------- /MobileDeepLinking-iOSTests/ExecuteHandlersTest.m: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | #import "MobileDeepLinking_Private.h" 25 | #import "MDLHandlerExecutor.h" 26 | 27 | #define EXP_SHORTHAND 28 | 29 | #import 30 | 31 | @interface ExecuteHandlersTest : XCTestCase 32 | 33 | @end 34 | 35 | @implementation ExecuteHandlersTest 36 | { 37 | MobileDeepLinking *mobileDeepLinking; 38 | NSDictionary *routeOptions; 39 | } 40 | 41 | - (void)setUp 42 | { 43 | [super setUp]; 44 | mobileDeepLinking = [MobileDeepLinking sharedInstance]; 45 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys:[[NSArray alloc] initWithObjects:@"testHandler", nil], @"handlers", nil]; 46 | } 47 | 48 | - (void)testHandlerExecutes 49 | { 50 | NSMutableDictionary * handlers = [[NSMutableDictionary alloc]init]; 51 | [handlers setObject:^void(NSDictionary *params) 52 | { 53 | [params setValue:@"value" forKey:@"name"]; 54 | } forKey:@"testHandler"]; 55 | 56 | NSMutableDictionary *routeParams = [[NSMutableDictionary alloc] init]; 57 | [MDLHandlerExecutor executeHandlers:routeOptions routeParams:routeParams handlers:handlers error:NULL]; 58 | 59 | NSMutableDictionary *expected = [[NSMutableDictionary alloc] initWithObjectsAndKeys:@"value", @"name", nil]; 60 | expect(routeParams).to.equal(expected); 61 | } 62 | 63 | - (void)testMultipleHandlersExecuteInOrder 64 | { 65 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys: 66 | [[NSArray alloc] initWithObjects:@"testHandler", @"testHandler2", nil], @"handlers", nil]; 67 | 68 | NSMutableDictionary * handlers = [[NSMutableDictionary alloc]init]; 69 | [handlers setObject:^void(NSDictionary *params) 70 | { 71 | [params setValue:@"value" forKey:@"name"]; 72 | } forKey:@"testHandler" 73 | ]; 74 | 75 | [handlers setObject:^void(NSDictionary *params) 76 | { 77 | [params setValue:@"value2" forKey:@"name"]; 78 | } forKey:@"testHandler2" 79 | ]; 80 | 81 | NSMutableDictionary *routeParams = [[NSMutableDictionary alloc] init]; 82 | [MDLHandlerExecutor executeHandlers:routeOptions routeParams:routeParams handlers:handlers error:NULL ]; 83 | 84 | NSMutableDictionary *expected = [[NSMutableDictionary alloc] initWithObjectsAndKeys:@"value2", @"name", nil]; 85 | expect(routeParams).to.equal(expected); 86 | } 87 | 88 | - (void)testMultipleHandlersExecuteInDifferentOrder 89 | { 90 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys: 91 | [[NSArray alloc] initWithObjects:@"testHandler2", @"testHandler", nil], @"handlers", nil]; 92 | 93 | 94 | NSMutableDictionary * handlers = [[NSMutableDictionary alloc]init]; 95 | [handlers setObject:^void(NSDictionary *params) 96 | { 97 | [params setValue:@"value" forKey:@"name"]; 98 | } forKey:@"testHandler" 99 | ]; 100 | 101 | [handlers setObject:^void(NSDictionary *params) 102 | { 103 | [params setValue:@"value2" forKey:@"name"]; 104 | } forKey:@"testHandler2" 105 | ]; 106 | 107 | NSMutableDictionary *routeParams = [[NSMutableDictionary alloc] init]; 108 | [MDLHandlerExecutor executeHandlers:routeOptions routeParams:routeParams handlers:handlers error:NULL ]; 109 | 110 | NSMutableDictionary *expected = [[NSMutableDictionary alloc] initWithObjectsAndKeys:@"value", @"name", nil]; 111 | expect(routeParams).to.equal(expected); 112 | } 113 | 114 | @end 115 | -------------------------------------------------------------------------------- /MobileDeepLinking-iOSTests/GetRequiredRouteParameterValuesTest.m: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | 24 | #import 25 | 26 | #define EXP_SHORTHAND 27 | 28 | #import 29 | #import "MobileDeepLinking.h" 30 | #import "MobileDeepLinking_Private.h" 31 | #import "MDLDeeplinkMatcher.h" 32 | 33 | @interface GetRequiredRouteParameterValuesTest : XCTestCase 34 | 35 | @end 36 | 37 | @implementation GetRequiredRouteParameterValuesTest 38 | { 39 | MobileDeepLinking *mobileDeepLinking; 40 | NSDictionary *routeOptions; 41 | } 42 | 43 | - (void)setUp 44 | { 45 | [super setUp]; 46 | mobileDeepLinking = [MobileDeepLinking sharedInstance]; 47 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys: 48 | [[NSDictionary alloc] initWithObjectsAndKeys: 49 | [[NSDictionary alloc] initWithObjectsAndKeys:@"true", @"required", nil], @"name" 50 | , nil], @"routeParameters", nil]; 51 | } 52 | 53 | - (void)testGetRequiredRouteParameterValues 54 | { 55 | NSMutableDictionary *expected = [[NSMutableDictionary alloc] initWithObjectsAndKeys:@YES, @"name", nil]; 56 | expect([MDLDeeplinkMatcher getRequiredRouteParameterValues:routeOptions]) 57 | .to.equal(expected); 58 | } 59 | 60 | - (void)testGetRequiredRouteParameterValuesWithoutAnyRequiredValues 61 | { 62 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys: 63 | [[NSDictionary alloc] initWithObjectsAndKeys: 64 | [[NSDictionary alloc] initWithObjectsAndKeys:@"false", @"required", nil], @"name" 65 | , nil], @"routeParameters", nil]; 66 | 67 | NSMutableDictionary *expected = [[NSMutableDictionary alloc] init]; 68 | expect([MDLDeeplinkMatcher getRequiredRouteParameterValues:routeOptions]) 69 | .to.equal(expected); 70 | } 71 | 72 | - (void)testGetRequiredRouteParameterValuesWithoutAnyValues 73 | { 74 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys: 75 | [[NSDictionary alloc] initWithObjectsAndKeys: 76 | [[NSDictionary alloc] init], @"name" 77 | , nil], @"routeParameters", nil]; 78 | 79 | NSMutableDictionary *expected = [[NSMutableDictionary alloc] init]; 80 | expect([MDLDeeplinkMatcher getRequiredRouteParameterValues:routeOptions]) 81 | .to.equal(expected); 82 | } 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /MobileDeepLinking-iOSTests/MatchPathParameterTest.m: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | #import "MobileDeepLinking_Private.h" 25 | #import "MDLDeeplinkMatcher.h" 26 | 27 | #define EXP_SHORTHAND 28 | 29 | #import 30 | 31 | @interface MatchPathParameterTest : XCTestCase 32 | 33 | @end 34 | 35 | @implementation MatchPathParameterTest 36 | { 37 | MobileDeepLinking *mobileDeepLinking; 38 | NSDictionary *routeOptions; 39 | NSMutableDictionary *results; 40 | NSError *error; 41 | } 42 | 43 | - (void)setUp 44 | { 45 | [super setUp]; 46 | mobileDeepLinking = [MobileDeepLinking sharedInstance]; 47 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys:@"routeParameters", [[NSDictionary alloc] init], nil]; 48 | results = [[NSMutableDictionary alloc] init]; 49 | error = nil; 50 | } 51 | 52 | - (void)tearDown 53 | { 54 | [super tearDown]; 55 | } 56 | 57 | #pragma mark - match path parameters 58 | 59 | - (void)testMatcherReturnTrueWithHost 60 | { 61 | expect([MDLDeeplinkMatcher matchPathParameters:@"data" routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:@"mdldemo://data"] results:results error:nil] 62 | ).to.equal(YES); 63 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 64 | } 65 | 66 | - (void)testMatcherReturnFalseWithHost 67 | { 68 | expect([MDLDeeplinkMatcher matchPathParameters:@"data" routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:@"mdldemo://dataa"] results:results error:nil] 69 | ).to.equal(NO); 70 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 71 | } 72 | 73 | - (void)testMatcherReturnFalseWithHost2 74 | { 75 | expect([MDLDeeplinkMatcher matchPathParameters:@"data" routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:@"mdldemo://ata"] results:results error:nil] 76 | ).to.equal(NO); 77 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 78 | } 79 | 80 | - (void)testMatcherReturnFalseWithHost3 81 | { 82 | expect([MDLDeeplinkMatcher matchPathParameters:@"data" routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:@"mdldemo://dat"] results:results error:nil] 83 | ).to.equal(NO); 84 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 85 | } 86 | 87 | - (void)testMatcherReturnTrueWithPath 88 | { 89 | NSString *path = @"data/path"; 90 | NSString *url = @"mdldemo://data/path"; 91 | 92 | expect([MDLDeeplinkMatcher matchPathParameters:@"data" routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:url] results:results error:nil] 93 | ).to.equal(NO); 94 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 95 | 96 | expect([MDLDeeplinkMatcher matchPathParameters:path routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:url] results:results error:nil] 97 | ).to.equal(YES); 98 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 99 | } 100 | 101 | - (void)testMatcherReturnTrueWithPathAndTrailingSlash 102 | { 103 | NSString *path = @"data/path"; 104 | NSString *url = @"mdldemo://data/path/"; 105 | expect([MDLDeeplinkMatcher matchPathParameters:@"data" routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:url] results:results error:nil] 106 | ).to.equal(NO); 107 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 108 | 109 | expect([MDLDeeplinkMatcher matchPathParameters:path routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:url] results:results error:nil] 110 | ).to.equal(YES); 111 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 112 | } 113 | 114 | - (void)testMatcherReturnFalseWithPath 115 | { 116 | NSString *path = @"data/path"; 117 | NSString *url = @"mdldemo://data/pathe"; 118 | expect([MDLDeeplinkMatcher matchPathParameters:@"data" routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:url] results:results error:nil] 119 | ).to.equal(NO); 120 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 121 | 122 | expect([MDLDeeplinkMatcher matchPathParameters:path routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:url] results:results error:nil] 123 | ).to.equal(NO); 124 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 125 | } 126 | 127 | - (void)testMatcherReturnFalseWithPath2 128 | { 129 | NSString *path = @"data/path"; 130 | NSString *url = @"mdldemo://data/pat"; 131 | expect([MDLDeeplinkMatcher matchPathParameters:@"data" routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:url] results:results error:nil] 132 | ).to.equal(NO); 133 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 134 | 135 | expect([MDLDeeplinkMatcher matchPathParameters:path routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:url] results:results error:nil] 136 | ).to.equal(NO); 137 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 138 | } 139 | 140 | - (void)testMatcherReturnFalseWithPath3 141 | { 142 | NSString *path = @"data/path"; 143 | NSString *url = @"mdldemo://daa/path"; 144 | expect([MDLDeeplinkMatcher matchPathParameters:@"data" routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:url] results:results error:nil] 145 | ).to.equal(NO); 146 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 147 | 148 | expect([MDLDeeplinkMatcher matchPathParameters:path routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:url] results:results error:nil] 149 | ).to.equal(NO); 150 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 151 | } 152 | 153 | - (void)testMatcherReturnTrueWithPathParams 154 | { 155 | NSString *path = @"data/path/:pathId"; 156 | NSString *url = @"mdldemo://data/path/5"; 157 | expect([MDLDeeplinkMatcher matchPathParameters:@"data" routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:url] results:results error:nil] 158 | ).to.equal(NO); 159 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 160 | 161 | expect([MDLDeeplinkMatcher matchPathParameters:@"data/path" routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:url] results:results error:nil] 162 | ).to.equal(NO); 163 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 164 | 165 | expect([MDLDeeplinkMatcher matchPathParameters:path routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:url] results:results error:nil] 166 | ).to.equal(YES); 167 | NSMutableDictionary *expected = [[NSMutableDictionary alloc] initWithObjectsAndKeys:@"5", @"pathId", nil]; 168 | expect(results).to.equal(expected); 169 | } 170 | 171 | - (void)testMatcherReturnTrueWithPathParamsAndTrailingSlash 172 | { 173 | NSString *path = @"data/path/:pathId"; 174 | NSString *url = @"mdldemo://data/path/5/"; 175 | expect([MDLDeeplinkMatcher matchPathParameters:@"data" routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:url] results:results error:nil] 176 | ).to.equal(NO); 177 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 178 | 179 | expect([MDLDeeplinkMatcher matchPathParameters:@"data/path" routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:url] results:results error:nil] 180 | ).to.equal(NO); 181 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 182 | 183 | expect([MDLDeeplinkMatcher matchPathParameters:path routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:url] results:results error:nil] 184 | ).to.equal(YES); 185 | NSMutableDictionary *expected = [[NSMutableDictionary alloc] initWithObjectsAndKeys:@"5", @"pathId", nil]; 186 | expect(results).to.equal(expected); 187 | } 188 | 189 | - (void)testMatcherReturnFalseWithPathParams 190 | { 191 | NSString *path = @"data/path/:pathId"; 192 | NSString *url = @"mdldemo://data/path//"; 193 | expect([MDLDeeplinkMatcher matchPathParameters:@"data" routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:url] results:results error:nil] 194 | ).to.equal(NO); 195 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 196 | 197 | expect([MDLDeeplinkMatcher matchPathParameters:@"data/path" routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:url] results:results error:nil] 198 | ).to.equal(YES); 199 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 200 | 201 | expect([MDLDeeplinkMatcher matchPathParameters:path routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:url] results:results error:nil] 202 | ).to.equal(NO); 203 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 204 | } 205 | 206 | - (void)testMatcherReturnTrueWithRegex 207 | { 208 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys:[[NSDictionary alloc] initWithObjectsAndKeys: 209 | [[NSDictionary alloc] initWithObjectsAndKeys:@"[0-9]", @"regex", nil], @"dataId", nil], @"routeParameters", nil]; 210 | 211 | expect([MDLDeeplinkMatcher matchPathParameters:@"data/:dataId" routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:@"mdldemo://data/5"] results:results error:nil] 212 | ).to.equal(YES); 213 | NSMutableDictionary *expected = [[NSMutableDictionary alloc] initWithObjectsAndKeys:@"5", @"dataId", nil]; 214 | expect(results).to.equal(expected); 215 | } 216 | 217 | - (void)testMatcherReturnFalseWithRegex 218 | { 219 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys:[[NSDictionary alloc] initWithObjectsAndKeys: 220 | [[NSDictionary alloc] initWithObjectsAndKeys:@"[0-9]", @"regex", nil], @"dataId", nil], @"routeParameters", nil]; 221 | 222 | expect([MDLDeeplinkMatcher matchPathParameters:@"data/:dataId" routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:@"mdldemo://data/52"] results:results error:nil] 223 | ).to.equal(NO); 224 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 225 | } 226 | 227 | - (void)testMatcherReturnFalseWithRegex2 228 | { 229 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys:[[NSDictionary alloc] initWithObjectsAndKeys: 230 | [[NSDictionary alloc] initWithObjectsAndKeys:@"[0-9]", @"regex", nil], @"dataId", nil], @"routeParameters", nil]; 231 | 232 | expect([MDLDeeplinkMatcher matchPathParameters:@"data/:dataId" routeOptions:routeOptions deeplink:[[NSURL alloc] initWithString:@"mdldemo://data/somedata"] results:results error:nil] 233 | ).to.equal(NO); 234 | expect(results).to.equal([[NSMutableDictionary alloc] init]); 235 | } 236 | 237 | 238 | @end 239 | -------------------------------------------------------------------------------- /MobileDeepLinking-iOSTests/MatchQueryParameterTest.m: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | #define EXP_SHORTHAND 26 | 27 | #import 28 | #import "MobileDeepLinking.h" 29 | #import "MobileDeepLinking_Private.h" 30 | #import "MDLDeeplinkMatcher.h" 31 | 32 | @interface MatchQueryParameterTest : XCTestCase 33 | 34 | @end 35 | 36 | @implementation MatchQueryParameterTest 37 | { 38 | MobileDeepLinking *mobileDeepLinking; 39 | NSDictionary *routeOptions; 40 | NSMutableDictionary *results; 41 | } 42 | 43 | - (void)setUp 44 | { 45 | [super setUp]; 46 | mobileDeepLinking = [MobileDeepLinking sharedInstance]; 47 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys:@"routeParameters", [[NSDictionary alloc] init], nil]; 48 | results = [[NSMutableDictionary alloc] init]; 49 | 50 | } 51 | 52 | - (void)tearDown 53 | { 54 | // Put teardown code here; it will be run once, after the last test case. 55 | [super tearDown]; 56 | } 57 | 58 | 59 | - (void)testQueryMatcherDoesntMatch 60 | { 61 | results = [[NSMutableDictionary alloc] init]; 62 | NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; 63 | expect([MDLDeeplinkMatcher matchQueryParameters:@"name=value" routeOptions:routeOptions result:results error:nil] 64 | ).to.equal(YES); 65 | expect(results).to.equal(dict); 66 | } 67 | 68 | - (void)testQueryMatcherDoesntMatchWithMultipleParameters 69 | { 70 | results = [[NSMutableDictionary alloc] init]; 71 | NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; 72 | expect([MDLDeeplinkMatcher matchQueryParameters:@"name=value&name2=value2" routeOptions:routeOptions result:results error:nil] 73 | ).to.equal(YES); 74 | expect(results).to.equal(dict); 75 | } 76 | 77 | - (void)testQueryMatcherMatch 78 | { 79 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys:[[NSDictionary alloc] initWithObjectsAndKeys: 80 | [[NSDictionary alloc] init], @"name", nil], @"routeParameters", nil]; 81 | 82 | NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; 83 | [dict setValue:@"value" forKey:@"name"]; 84 | expect([MDLDeeplinkMatcher matchQueryParameters:@"name=value" routeOptions:routeOptions result:results error:nil] 85 | ).to.equal(YES); 86 | expect(results).to.equal(dict); 87 | } 88 | 89 | - (void)testQueryMatcherMatchWithMultipleParameters 90 | { 91 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys:[[NSDictionary alloc] initWithObjectsAndKeys: 92 | [[NSDictionary alloc] init], @"name", nil], @"routeParameters", nil]; 93 | 94 | NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; 95 | [dict setValue:@"value" forKey:@"name"]; 96 | 97 | expect([MDLDeeplinkMatcher matchQueryParameters:@"name=value&name2=value2" routeOptions:routeOptions result:results error:nil] 98 | ).to.equal(YES); 99 | expect(results).to.equal(dict); 100 | } 101 | 102 | - (void)testQueryMatcherMatchWithMultipleParameters2 103 | { 104 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys:[[NSDictionary alloc] initWithObjectsAndKeys: 105 | [[NSDictionary alloc] init], @"name2", nil], @"routeParameters", nil]; 106 | 107 | NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; 108 | [dict setValue:@"value2" forKey:@"name2"]; 109 | 110 | expect([MDLDeeplinkMatcher matchQueryParameters:@"name=value&name2=value2" routeOptions:routeOptions result:results error:nil] 111 | ).to.equal(YES); 112 | expect(results).to.equal(dict); 113 | } 114 | 115 | - (void)testQueryMatcherMatchWithMultipleParameters3 116 | { 117 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys:[[NSDictionary alloc] initWithObjectsAndKeys: 118 | [[NSDictionary alloc] init], @"name", [[NSDictionary alloc] init], @"name2", nil], @"routeParameters", nil]; 119 | 120 | NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; 121 | [dict setValue:@"value" forKey:@"name"]; 122 | [dict setValue:@"value2" forKey:@"name2"]; 123 | 124 | expect([MDLDeeplinkMatcher matchQueryParameters:@"name=value&name2=value2" routeOptions:routeOptions result:results error:nil] 125 | ).to.equal(YES); 126 | expect(results).to.equal(dict); 127 | } 128 | 129 | - (void)testQueryMatcherMatchWithRegexParameter 130 | { 131 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys:[[NSDictionary alloc] initWithObjectsAndKeys: 132 | [[NSDictionary alloc] initWithObjectsAndKeys:@"[0-9]", @"regex", nil], @"name", nil], @"routeParameters", nil]; 133 | 134 | NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; 135 | [dict setValue:@"6" forKey:@"name"]; 136 | 137 | expect([MDLDeeplinkMatcher matchQueryParameters:@"name=6&name2=value2" routeOptions:routeOptions result:results error:nil] 138 | ).to.equal(YES); 139 | expect(results).to.equal(dict); 140 | 141 | results = [[NSMutableDictionary alloc] init]; 142 | expect([MDLDeeplinkMatcher matchQueryParameters:@"name=62&name2=value2" routeOptions:routeOptions result:results error:nil] 143 | ).to.equal(NO); 144 | } 145 | 146 | @end 147 | -------------------------------------------------------------------------------- /MobileDeepLinking-iOSTests/MobileDeepLinkingTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.mobiledeeplinking.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /MobileDeepLinking-iOSTests/RegexValidationTest.m: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | #define EXP_SHORTHAND 26 | 27 | #import 28 | #import "MobileDeepLinking.h" 29 | #import "MobileDeepLinking_Private.h" 30 | #import "MDLDeeplinkMatcher.h" 31 | 32 | @interface RegexValidationTest : XCTestCase 33 | 34 | @end 35 | 36 | @implementation RegexValidationTest 37 | { 38 | MobileDeepLinking *mobileDeepLinking; 39 | NSDictionary *routeOptions; 40 | NSMutableDictionary *results; 41 | } 42 | 43 | - (void)setUp 44 | { 45 | [super setUp]; 46 | mobileDeepLinking = [MobileDeepLinking sharedInstance]; 47 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys:@"routeParameters", [[NSDictionary alloc] init], nil]; 48 | results = [[NSMutableDictionary alloc] init]; 49 | 50 | } 51 | 52 | - (void)tearDown 53 | { 54 | // Put teardown code here; it will be run once, after the last test case. 55 | [super tearDown]; 56 | } 57 | 58 | - (void)testRegexMatches 59 | { 60 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys:[[NSDictionary alloc] initWithObjectsAndKeys: 61 | [[NSDictionary alloc] initWithObjectsAndKeys:@"[0-9]", @"regex", nil], @"name", nil], @"routeParameters", nil]; 62 | expect([MDLDeeplinkMatcher validateRouteComponent:@"name" value:@"3" routeOptions:routeOptions]) 63 | .to.equal(YES); 64 | } 65 | 66 | - (void)testRegexDoesNotMatch 67 | { 68 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys:[[NSDictionary alloc] initWithObjectsAndKeys: 69 | [[NSDictionary alloc] initWithObjectsAndKeys:@"[0-9]", @"regex", nil], @"name", nil], @"routeParameters", nil]; 70 | expect([MDLDeeplinkMatcher validateRouteComponent:@"name" value:@"32" routeOptions:routeOptions]) 71 | .to.equal(NO); 72 | } 73 | 74 | - (void)testRegexDoesNotMatch2 75 | { 76 | routeOptions = [[NSDictionary alloc] initWithObjectsAndKeys:[[NSDictionary alloc] initWithObjectsAndKeys: 77 | [[NSDictionary alloc] initWithObjectsAndKeys:@"[0-9]", @"regex", nil], @"name", nil], @"routeParameters", nil]; 78 | expect([MDLDeeplinkMatcher validateRouteComponent:@"name" value:@"hello" routeOptions:routeOptions]) 79 | .to.equal(NO); 80 | } 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /MobileDeepLinking-iOSTests/TrimDeeplinkTest.m: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | #define EXP_SHORTHAND 26 | 27 | #import 28 | #import "MobileDeepLinking.h" 29 | #import "MobileDeepLinking_Private.h" 30 | 31 | @interface TrimDeeplinkTest : XCTestCase 32 | 33 | @end 34 | 35 | @implementation TrimDeeplinkTest 36 | { 37 | MobileDeepLinking *mobileDeepLinking; 38 | } 39 | 40 | - (void)setUp 41 | { 42 | [super setUp]; 43 | mobileDeepLinking = [MobileDeepLinking sharedInstance]; 44 | } 45 | 46 | - (void)testTrimDeeplink 47 | { 48 | NSURL *url = [[NSURL alloc] initWithString:@"mdldemo://data/54?name=value&name1=value1"]; 49 | NSURL *expected = [[NSURL alloc] initWithString:@"mdldemo://data?name=value&name1=value1"]; 50 | expect([mobileDeepLinking trimDeeplink:url]) 51 | .to.equal(expected); 52 | } 53 | 54 | - (void)testTrimDeeplinkWithTrailingSlashes 55 | { 56 | NSURL *url = [[NSURL alloc] initWithString:@"mdldemo://data/54/?name=value&name1=value1"]; 57 | NSURL *expected = [[NSURL alloc] initWithString:@"mdldemo://data?name=value&name1=value1"]; 58 | expect([mobileDeepLinking trimDeeplink:url]) 59 | .to.equal(expected); 60 | 61 | 62 | url = [[NSURL alloc] initWithString:@"mdldemo://data/54//////?name=value&name1=value1"]; 63 | expected = [[NSURL alloc] initWithString:@"mdldemo://data?name=value&name1=value1"]; 64 | expect([mobileDeepLinking trimDeeplink:url]) 65 | .to.equal(expected); 66 | } 67 | 68 | - (void)testTrimDeeplinkWithoutPath 69 | { 70 | NSURL *url = [[NSURL alloc] initWithString:@"mdldemo://data?name=value&name1=value1"]; 71 | NSURL *expected = [[NSURL alloc] initWithString:@"mdldemo://?name=value&name1=value1"]; 72 | expect([mobileDeepLinking trimDeeplink:url]) 73 | .to.equal(expected); 74 | } 75 | 76 | - (void)testTrimDeeplinkWithoutHostAndPath 77 | { 78 | NSURL *url = [[NSURL alloc] initWithString:@"mdldemo://?name=value&name1=value1"]; 79 | NSURL *expected = [[NSURL alloc] initWithString:@"mdldemo://?name=value&name1=value1"]; 80 | expect([mobileDeepLinking trimDeeplink:url]) 81 | .to.equal(expected); 82 | } 83 | 84 | - (void)testTrimDeeplinkWithLongPath 85 | { 86 | NSURL *url = [[NSURL alloc] initWithString:@"mdldemo://data/32/hello/there?name=value&name1=value1"]; 87 | NSURL *expected = [[NSURL alloc] initWithString:@"mdldemo://data/32/hello?name=value&name1=value1"]; 88 | expect([mobileDeepLinking trimDeeplink:url]) 89 | .to.equal(expected); 90 | } 91 | 92 | - (void)testTrimDeeplinkWithHost 93 | { 94 | NSURL *url = [[NSURL alloc] initWithString:@"mdldemo://data?name=value&name1=value1"]; 95 | NSURL *expected = [[NSURL alloc] initWithString:@"mdldemo://?name=value&name1=value1"]; 96 | expect([mobileDeepLinking trimDeeplink:url]) 97 | .to.equal(expected); 98 | } 99 | 100 | - (void)testTrimDeeplinkWithHost2 101 | { 102 | NSURL *url = [[NSURL alloc] initWithString:@"mdldemo://data/3"]; 103 | NSURL *expected = [[NSURL alloc] initWithString:@"mdldemo://"]; 104 | expect([mobileDeepLinking trimDeeplink:[mobileDeepLinking trimDeeplink:url]]) 105 | .to.equal(expected); 106 | } 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /MobileDeepLinking-iOSTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /MobileDeepLinking.xcodeproj/xcshareddata/xcschemes/Framework.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 44 | 45 | 51 | 52 | 54 | 55 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /MobileDeepLinking.xcodeproj/xcshareddata/xcschemes/MobileDeepLinking-iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 57 | 58 | 59 | 60 | 61 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /MobileDeepLinking.xcodeproj/xcshareddata/xcschemes/Run Tests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 52 | 53 | 54 | 55 | 61 | 62 | 64 | 65 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 5C593AB375A039BB32D6AD63 /* StoryBoardViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C59369F0D18BA9037A28087 /* StoryBoardViewController.m */; }; 11 | AA81F543189966EB00EE8862 /* ViewControllerWithNib.m in Sources */ = {isa = PBXBuildFile; fileRef = AA81F541189966EB00EE8862 /* ViewControllerWithNib.m */; }; 12 | AA81F544189966EB00EE8862 /* ViewControllerWithNib.xib in Resources */ = {isa = PBXBuildFile; fileRef = AA81F542189966EB00EE8862 /* ViewControllerWithNib.xib */; }; 13 | AA81F54818996C1A00EE8862 /* NonIBViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AA81F54718996C1A00EE8862 /* NonIBViewController.m */; }; 14 | AABF8E32188F2D3400E35A09 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AABF8E31188F2D3400E35A09 /* Foundation.framework */; }; 15 | AABF8E34188F2D3400E35A09 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AABF8E33188F2D3400E35A09 /* CoreGraphics.framework */; }; 16 | AABF8E36188F2D3400E35A09 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AABF8E35188F2D3400E35A09 /* UIKit.framework */; }; 17 | AABF8E3C188F2D3400E35A09 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = AABF8E3A188F2D3400E35A09 /* InfoPlist.strings */; }; 18 | AABF8E3E188F2D3400E35A09 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = AABF8E3D188F2D3400E35A09 /* main.m */; }; 19 | AABF8E42188F2D3400E35A09 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = AABF8E41188F2D3400E35A09 /* AppDelegate.m */; }; 20 | AABF8E48188F2D3400E35A09 /* DataViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AABF8E47188F2D3400E35A09 /* DataViewController.m */; }; 21 | AABF8E4E188F2D3400E35A09 /* Main_iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AABF8E4C188F2D3400E35A09 /* Main_iPhone.storyboard */; }; 22 | AABF8E51188F2D3400E35A09 /* Main_iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AABF8E4F188F2D3400E35A09 /* Main_iPad.storyboard */; }; 23 | AABF8E53188F2D3400E35A09 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AABF8E52188F2D3400E35A09 /* Images.xcassets */; }; 24 | AABF8E5A188F2D3400E35A09 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AABF8E59188F2D3400E35A09 /* XCTest.framework */; }; 25 | AABF8E5B188F2D3400E35A09 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AABF8E31188F2D3400E35A09 /* Foundation.framework */; }; 26 | AABF8E5C188F2D3400E35A09 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AABF8E35188F2D3400E35A09 /* UIKit.framework */; }; 27 | AABF8E64188F2D3400E35A09 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = AABF8E62188F2D3400E35A09 /* InfoPlist.strings */; }; 28 | AABF8E66188F2D3400E35A09 /* MobileDeepLinkingDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AABF8E65188F2D3400E35A09 /* MobileDeepLinkingDemoTests.m */; }; 29 | AABF8E84188F2E5800E35A09 /* libMobileDeepLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AABF8E83188F2E5800E35A09 /* libMobileDeepLinking.a */; }; 30 | AABF8E86188F333900E35A09 /* MobileDeepLinkingConfig.json in Resources */ = {isa = PBXBuildFile; fileRef = AABF8E85188F333900E35A09 /* MobileDeepLinkingConfig.json */; }; 31 | /* End PBXBuildFile section */ 32 | 33 | /* Begin PBXContainerItemProxy section */ 34 | AABF8E5D188F2D3400E35A09 /* PBXContainerItemProxy */ = { 35 | isa = PBXContainerItemProxy; 36 | containerPortal = AABF8E26188F2D3300E35A09 /* Project object */; 37 | proxyType = 1; 38 | remoteGlobalIDString = AABF8E2D188F2D3400E35A09; 39 | remoteInfo = MobileDeepLinkingDemo; 40 | }; 41 | /* End PBXContainerItemProxy section */ 42 | 43 | /* Begin PBXFileReference section */ 44 | 5C59369F0D18BA9037A28087 /* StoryBoardViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StoryBoardViewController.m; sourceTree = ""; }; 45 | 5C593B9E3E10323A07BAB0CC /* StoryBoardViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StoryBoardViewController.h; sourceTree = ""; }; 46 | AA81F540189966EB00EE8862 /* ViewControllerWithNib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewControllerWithNib.h; sourceTree = ""; }; 47 | AA81F541189966EB00EE8862 /* ViewControllerWithNib.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewControllerWithNib.m; sourceTree = ""; }; 48 | AA81F542189966EB00EE8862 /* ViewControllerWithNib.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ViewControllerWithNib.xib; sourceTree = ""; }; 49 | AA81F54618996C1A00EE8862 /* NonIBViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NonIBViewController.h; sourceTree = ""; }; 50 | AA81F54718996C1A00EE8862 /* NonIBViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NonIBViewController.m; sourceTree = ""; }; 51 | AABF8E2E188F2D3400E35A09 /* MobileDeepLinkingDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MobileDeepLinkingDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | AABF8E31188F2D3400E35A09 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 53 | AABF8E33188F2D3400E35A09 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 54 | AABF8E35188F2D3400E35A09 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 55 | AABF8E39188F2D3400E35A09 /* MobileDeepLinkingDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "MobileDeepLinkingDemo-Info.plist"; sourceTree = ""; }; 56 | AABF8E3B188F2D3400E35A09 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 57 | AABF8E3D188F2D3400E35A09 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 58 | AABF8E3F188F2D3400E35A09 /* MobileDeepLinkingDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MobileDeepLinkingDemo-Prefix.pch"; sourceTree = ""; }; 59 | AABF8E40188F2D3400E35A09 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 60 | AABF8E41188F2D3400E35A09 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 61 | AABF8E46188F2D3400E35A09 /* DataViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DataViewController.h; sourceTree = ""; }; 62 | AABF8E47188F2D3400E35A09 /* DataViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DataViewController.m; sourceTree = ""; }; 63 | AABF8E4D188F2D3400E35A09 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main_iPhone.storyboard; sourceTree = ""; }; 64 | AABF8E50188F2D3400E35A09 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main_iPad.storyboard; sourceTree = ""; }; 65 | AABF8E52188F2D3400E35A09 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 66 | AABF8E58188F2D3400E35A09 /* MobileDeepLinkingDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MobileDeepLinkingDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 67 | AABF8E59188F2D3400E35A09 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 68 | AABF8E61188F2D3400E35A09 /* MobileDeepLinkingDemoTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "MobileDeepLinkingDemoTests-Info.plist"; sourceTree = ""; }; 69 | AABF8E63188F2D3400E35A09 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 70 | AABF8E65188F2D3400E35A09 /* MobileDeepLinkingDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MobileDeepLinkingDemoTests.m; sourceTree = ""; }; 71 | AABF8E83188F2E5800E35A09 /* libMobileDeepLinking.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libMobileDeepLinking.a; path = "../../../Library/Developer/Xcode/DerivedData/MobileDeepLinking-gfuxzmkstjruakdecxfaohfnfwhq/Build/Products/Debug-iphoneos/libMobileDeepLinking.a"; sourceTree = ""; }; 72 | AABF8E85188F333900E35A09 /* MobileDeepLinkingConfig.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = MobileDeepLinkingConfig.json; sourceTree = ""; }; 73 | /* End PBXFileReference section */ 74 | 75 | /* Begin PBXFrameworksBuildPhase section */ 76 | AABF8E2B188F2D3400E35A09 /* Frameworks */ = { 77 | isa = PBXFrameworksBuildPhase; 78 | buildActionMask = 2147483647; 79 | files = ( 80 | AABF8E84188F2E5800E35A09 /* libMobileDeepLinking.a in Frameworks */, 81 | AABF8E34188F2D3400E35A09 /* CoreGraphics.framework in Frameworks */, 82 | AABF8E36188F2D3400E35A09 /* UIKit.framework in Frameworks */, 83 | AABF8E32188F2D3400E35A09 /* Foundation.framework in Frameworks */, 84 | ); 85 | runOnlyForDeploymentPostprocessing = 0; 86 | }; 87 | AABF8E55188F2D3400E35A09 /* Frameworks */ = { 88 | isa = PBXFrameworksBuildPhase; 89 | buildActionMask = 2147483647; 90 | files = ( 91 | AABF8E5A188F2D3400E35A09 /* XCTest.framework in Frameworks */, 92 | AABF8E5C188F2D3400E35A09 /* UIKit.framework in Frameworks */, 93 | AABF8E5B188F2D3400E35A09 /* Foundation.framework in Frameworks */, 94 | ); 95 | runOnlyForDeploymentPostprocessing = 0; 96 | }; 97 | /* End PBXFrameworksBuildPhase section */ 98 | 99 | /* Begin PBXGroup section */ 100 | AA81F5391899669A00EE8862 /* Storyboard Views */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 5C593B9E3E10323A07BAB0CC /* StoryBoardViewController.h */, 104 | 5C59369F0D18BA9037A28087 /* StoryBoardViewController.m */, 105 | AABF8E46188F2D3400E35A09 /* DataViewController.h */, 106 | AABF8E47188F2D3400E35A09 /* DataViewController.m */, 107 | ); 108 | name = "Storyboard Views"; 109 | sourceTree = ""; 110 | }; 111 | AA81F53A189966B400EE8862 /* Nib Views */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | AA81F540189966EB00EE8862 /* ViewControllerWithNib.h */, 115 | AA81F541189966EB00EE8862 /* ViewControllerWithNib.m */, 116 | AA81F542189966EB00EE8862 /* ViewControllerWithNib.xib */, 117 | ); 118 | name = "Nib Views"; 119 | sourceTree = ""; 120 | }; 121 | AA81F54518996C0300EE8862 /* Non-IB Views */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | AA81F54618996C1A00EE8862 /* NonIBViewController.h */, 125 | AA81F54718996C1A00EE8862 /* NonIBViewController.m */, 126 | ); 127 | name = "Non-IB Views"; 128 | sourceTree = ""; 129 | }; 130 | AABF8E25188F2D3300E35A09 = { 131 | isa = PBXGroup; 132 | children = ( 133 | AABF8E37188F2D3400E35A09 /* MobileDeepLinkingDemo */, 134 | AABF8E5F188F2D3400E35A09 /* MobileDeepLinkingDemoTests */, 135 | AABF8E30188F2D3400E35A09 /* Frameworks */, 136 | AABF8E2F188F2D3400E35A09 /* Products */, 137 | ); 138 | sourceTree = ""; 139 | }; 140 | AABF8E2F188F2D3400E35A09 /* Products */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | AABF8E2E188F2D3400E35A09 /* MobileDeepLinkingDemo.app */, 144 | AABF8E58188F2D3400E35A09 /* MobileDeepLinkingDemoTests.xctest */, 145 | ); 146 | name = Products; 147 | sourceTree = ""; 148 | }; 149 | AABF8E30188F2D3400E35A09 /* Frameworks */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | AABF8E83188F2E5800E35A09 /* libMobileDeepLinking.a */, 153 | AABF8E31188F2D3400E35A09 /* Foundation.framework */, 154 | AABF8E33188F2D3400E35A09 /* CoreGraphics.framework */, 155 | AABF8E35188F2D3400E35A09 /* UIKit.framework */, 156 | AABF8E59188F2D3400E35A09 /* XCTest.framework */, 157 | ); 158 | name = Frameworks; 159 | sourceTree = ""; 160 | }; 161 | AABF8E37188F2D3400E35A09 /* MobileDeepLinkingDemo */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | AA81F54518996C0300EE8862 /* Non-IB Views */, 165 | AA81F53A189966B400EE8862 /* Nib Views */, 166 | AA81F5391899669A00EE8862 /* Storyboard Views */, 167 | AABF8E40188F2D3400E35A09 /* AppDelegate.h */, 168 | AABF8E41188F2D3400E35A09 /* AppDelegate.m */, 169 | AABF8E4C188F2D3400E35A09 /* Main_iPhone.storyboard */, 170 | AABF8E4F188F2D3400E35A09 /* Main_iPad.storyboard */, 171 | AABF8E52188F2D3400E35A09 /* Images.xcassets */, 172 | AABF8E38188F2D3400E35A09 /* Supporting Files */, 173 | ); 174 | path = MobileDeepLinkingDemo; 175 | sourceTree = ""; 176 | }; 177 | AABF8E38188F2D3400E35A09 /* Supporting Files */ = { 178 | isa = PBXGroup; 179 | children = ( 180 | AABF8E85188F333900E35A09 /* MobileDeepLinkingConfig.json */, 181 | AABF8E39188F2D3400E35A09 /* MobileDeepLinkingDemo-Info.plist */, 182 | AABF8E3A188F2D3400E35A09 /* InfoPlist.strings */, 183 | AABF8E3D188F2D3400E35A09 /* main.m */, 184 | AABF8E3F188F2D3400E35A09 /* MobileDeepLinkingDemo-Prefix.pch */, 185 | ); 186 | name = "Supporting Files"; 187 | sourceTree = ""; 188 | }; 189 | AABF8E5F188F2D3400E35A09 /* MobileDeepLinkingDemoTests */ = { 190 | isa = PBXGroup; 191 | children = ( 192 | AABF8E65188F2D3400E35A09 /* MobileDeepLinkingDemoTests.m */, 193 | AABF8E60188F2D3400E35A09 /* Supporting Files */, 194 | ); 195 | path = MobileDeepLinkingDemoTests; 196 | sourceTree = ""; 197 | }; 198 | AABF8E60188F2D3400E35A09 /* Supporting Files */ = { 199 | isa = PBXGroup; 200 | children = ( 201 | AABF8E61188F2D3400E35A09 /* MobileDeepLinkingDemoTests-Info.plist */, 202 | AABF8E62188F2D3400E35A09 /* InfoPlist.strings */, 203 | ); 204 | name = "Supporting Files"; 205 | sourceTree = ""; 206 | }; 207 | /* End PBXGroup section */ 208 | 209 | /* Begin PBXNativeTarget section */ 210 | AABF8E2D188F2D3400E35A09 /* MobileDeepLinkingDemo */ = { 211 | isa = PBXNativeTarget; 212 | buildConfigurationList = AABF8E69188F2D3400E35A09 /* Build configuration list for PBXNativeTarget "MobileDeepLinkingDemo" */; 213 | buildPhases = ( 214 | AABF8E2A188F2D3400E35A09 /* Sources */, 215 | AABF8E2B188F2D3400E35A09 /* Frameworks */, 216 | AABF8E2C188F2D3400E35A09 /* Resources */, 217 | ); 218 | buildRules = ( 219 | ); 220 | dependencies = ( 221 | ); 222 | name = MobileDeepLinkingDemo; 223 | productName = MobileDeepLinkingDemo; 224 | productReference = AABF8E2E188F2D3400E35A09 /* MobileDeepLinkingDemo.app */; 225 | productType = "com.apple.product-type.application"; 226 | }; 227 | AABF8E57188F2D3400E35A09 /* MobileDeepLinkingDemoTests */ = { 228 | isa = PBXNativeTarget; 229 | buildConfigurationList = AABF8E6C188F2D3400E35A09 /* Build configuration list for PBXNativeTarget "MobileDeepLinkingDemoTests" */; 230 | buildPhases = ( 231 | AABF8E54188F2D3400E35A09 /* Sources */, 232 | AABF8E55188F2D3400E35A09 /* Frameworks */, 233 | AABF8E56188F2D3400E35A09 /* Resources */, 234 | ); 235 | buildRules = ( 236 | ); 237 | dependencies = ( 238 | AABF8E5E188F2D3400E35A09 /* PBXTargetDependency */, 239 | ); 240 | name = MobileDeepLinkingDemoTests; 241 | productName = MobileDeepLinkingDemoTests; 242 | productReference = AABF8E58188F2D3400E35A09 /* MobileDeepLinkingDemoTests.xctest */; 243 | productType = "com.apple.product-type.bundle.unit-test"; 244 | }; 245 | /* End PBXNativeTarget section */ 246 | 247 | /* Begin PBXProject section */ 248 | AABF8E26188F2D3300E35A09 /* Project object */ = { 249 | isa = PBXProject; 250 | attributes = { 251 | LastUpgradeCheck = 0500; 252 | ORGANIZATIONNAME = mobiledeeplinking; 253 | TargetAttributes = { 254 | AABF8E57188F2D3400E35A09 = { 255 | TestTargetID = AABF8E2D188F2D3400E35A09; 256 | }; 257 | }; 258 | }; 259 | buildConfigurationList = AABF8E29188F2D3300E35A09 /* Build configuration list for PBXProject "MobileDeepLinkingDemo" */; 260 | compatibilityVersion = "Xcode 3.2"; 261 | developmentRegion = English; 262 | hasScannedForEncodings = 0; 263 | knownRegions = ( 264 | en, 265 | Base, 266 | ); 267 | mainGroup = AABF8E25188F2D3300E35A09; 268 | productRefGroup = AABF8E2F188F2D3400E35A09 /* Products */; 269 | projectDirPath = ""; 270 | projectRoot = ""; 271 | targets = ( 272 | AABF8E2D188F2D3400E35A09 /* MobileDeepLinkingDemo */, 273 | AABF8E57188F2D3400E35A09 /* MobileDeepLinkingDemoTests */, 274 | ); 275 | }; 276 | /* End PBXProject section */ 277 | 278 | /* Begin PBXResourcesBuildPhase section */ 279 | AABF8E2C188F2D3400E35A09 /* Resources */ = { 280 | isa = PBXResourcesBuildPhase; 281 | buildActionMask = 2147483647; 282 | files = ( 283 | AABF8E51188F2D3400E35A09 /* Main_iPad.storyboard in Resources */, 284 | AABF8E53188F2D3400E35A09 /* Images.xcassets in Resources */, 285 | AABF8E86188F333900E35A09 /* MobileDeepLinkingConfig.json in Resources */, 286 | AABF8E4E188F2D3400E35A09 /* Main_iPhone.storyboard in Resources */, 287 | AA81F544189966EB00EE8862 /* ViewControllerWithNib.xib in Resources */, 288 | AABF8E3C188F2D3400E35A09 /* InfoPlist.strings in Resources */, 289 | ); 290 | runOnlyForDeploymentPostprocessing = 0; 291 | }; 292 | AABF8E56188F2D3400E35A09 /* Resources */ = { 293 | isa = PBXResourcesBuildPhase; 294 | buildActionMask = 2147483647; 295 | files = ( 296 | AABF8E64188F2D3400E35A09 /* InfoPlist.strings in Resources */, 297 | ); 298 | runOnlyForDeploymentPostprocessing = 0; 299 | }; 300 | /* End PBXResourcesBuildPhase section */ 301 | 302 | /* Begin PBXSourcesBuildPhase section */ 303 | AABF8E2A188F2D3400E35A09 /* Sources */ = { 304 | isa = PBXSourcesBuildPhase; 305 | buildActionMask = 2147483647; 306 | files = ( 307 | AABF8E48188F2D3400E35A09 /* DataViewController.m in Sources */, 308 | AABF8E42188F2D3400E35A09 /* AppDelegate.m in Sources */, 309 | AABF8E3E188F2D3400E35A09 /* main.m in Sources */, 310 | AA81F543189966EB00EE8862 /* ViewControllerWithNib.m in Sources */, 311 | AA81F54818996C1A00EE8862 /* NonIBViewController.m in Sources */, 312 | 5C593AB375A039BB32D6AD63 /* StoryBoardViewController.m in Sources */, 313 | ); 314 | runOnlyForDeploymentPostprocessing = 0; 315 | }; 316 | AABF8E54188F2D3400E35A09 /* Sources */ = { 317 | isa = PBXSourcesBuildPhase; 318 | buildActionMask = 2147483647; 319 | files = ( 320 | AABF8E66188F2D3400E35A09 /* MobileDeepLinkingDemoTests.m in Sources */, 321 | ); 322 | runOnlyForDeploymentPostprocessing = 0; 323 | }; 324 | /* End PBXSourcesBuildPhase section */ 325 | 326 | /* Begin PBXTargetDependency section */ 327 | AABF8E5E188F2D3400E35A09 /* PBXTargetDependency */ = { 328 | isa = PBXTargetDependency; 329 | target = AABF8E2D188F2D3400E35A09 /* MobileDeepLinkingDemo */; 330 | targetProxy = AABF8E5D188F2D3400E35A09 /* PBXContainerItemProxy */; 331 | }; 332 | /* End PBXTargetDependency section */ 333 | 334 | /* Begin PBXVariantGroup section */ 335 | AABF8E3A188F2D3400E35A09 /* InfoPlist.strings */ = { 336 | isa = PBXVariantGroup; 337 | children = ( 338 | AABF8E3B188F2D3400E35A09 /* en */, 339 | ); 340 | name = InfoPlist.strings; 341 | sourceTree = ""; 342 | }; 343 | AABF8E4C188F2D3400E35A09 /* Main_iPhone.storyboard */ = { 344 | isa = PBXVariantGroup; 345 | children = ( 346 | AABF8E4D188F2D3400E35A09 /* Base */, 347 | ); 348 | name = Main_iPhone.storyboard; 349 | sourceTree = ""; 350 | }; 351 | AABF8E4F188F2D3400E35A09 /* Main_iPad.storyboard */ = { 352 | isa = PBXVariantGroup; 353 | children = ( 354 | AABF8E50188F2D3400E35A09 /* Base */, 355 | ); 356 | name = Main_iPad.storyboard; 357 | sourceTree = ""; 358 | }; 359 | AABF8E62188F2D3400E35A09 /* InfoPlist.strings */ = { 360 | isa = PBXVariantGroup; 361 | children = ( 362 | AABF8E63188F2D3400E35A09 /* en */, 363 | ); 364 | name = InfoPlist.strings; 365 | sourceTree = ""; 366 | }; 367 | /* End PBXVariantGroup section */ 368 | 369 | /* Begin XCBuildConfiguration section */ 370 | AABF8E67188F2D3400E35A09 /* Debug */ = { 371 | isa = XCBuildConfiguration; 372 | buildSettings = { 373 | ALWAYS_SEARCH_USER_PATHS = NO; 374 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 375 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 376 | CLANG_CXX_LIBRARY = "libc++"; 377 | CLANG_ENABLE_MODULES = YES; 378 | CLANG_ENABLE_OBJC_ARC = YES; 379 | CLANG_WARN_BOOL_CONVERSION = YES; 380 | CLANG_WARN_CONSTANT_CONVERSION = YES; 381 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 382 | CLANG_WARN_EMPTY_BODY = YES; 383 | CLANG_WARN_ENUM_CONVERSION = YES; 384 | CLANG_WARN_INT_CONVERSION = YES; 385 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 386 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 387 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 388 | COPY_PHASE_STRIP = NO; 389 | GCC_C_LANGUAGE_STANDARD = gnu99; 390 | GCC_DYNAMIC_NO_PIC = NO; 391 | GCC_OPTIMIZATION_LEVEL = 0; 392 | GCC_PREPROCESSOR_DEFINITIONS = ( 393 | "DEBUG=1", 394 | "$(inherited)", 395 | ); 396 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 397 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 398 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 399 | GCC_WARN_UNDECLARED_SELECTOR = YES; 400 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 401 | GCC_WARN_UNUSED_FUNCTION = YES; 402 | GCC_WARN_UNUSED_VARIABLE = YES; 403 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 404 | ONLY_ACTIVE_ARCH = YES; 405 | SDKROOT = iphoneos; 406 | TARGETED_DEVICE_FAMILY = "1,2"; 407 | }; 408 | name = Debug; 409 | }; 410 | AABF8E68188F2D3400E35A09 /* Release */ = { 411 | isa = XCBuildConfiguration; 412 | buildSettings = { 413 | ALWAYS_SEARCH_USER_PATHS = NO; 414 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 415 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 416 | CLANG_CXX_LIBRARY = "libc++"; 417 | CLANG_ENABLE_MODULES = YES; 418 | CLANG_ENABLE_OBJC_ARC = YES; 419 | CLANG_WARN_BOOL_CONVERSION = YES; 420 | CLANG_WARN_CONSTANT_CONVERSION = YES; 421 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 422 | CLANG_WARN_EMPTY_BODY = YES; 423 | CLANG_WARN_ENUM_CONVERSION = YES; 424 | CLANG_WARN_INT_CONVERSION = YES; 425 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 426 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 427 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 428 | COPY_PHASE_STRIP = YES; 429 | ENABLE_NS_ASSERTIONS = NO; 430 | GCC_C_LANGUAGE_STANDARD = gnu99; 431 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 432 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 433 | GCC_WARN_UNDECLARED_SELECTOR = YES; 434 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 435 | GCC_WARN_UNUSED_FUNCTION = YES; 436 | GCC_WARN_UNUSED_VARIABLE = YES; 437 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 438 | SDKROOT = iphoneos; 439 | TARGETED_DEVICE_FAMILY = "1,2"; 440 | VALIDATE_PRODUCT = YES; 441 | }; 442 | name = Release; 443 | }; 444 | AABF8E6A188F2D3400E35A09 /* Debug */ = { 445 | isa = XCBuildConfiguration; 446 | buildSettings = { 447 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 448 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 449 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 450 | GCC_PREFIX_HEADER = "MobileDeepLinkingDemo/MobileDeepLinkingDemo-Prefix.pch"; 451 | INFOPLIST_FILE = "MobileDeepLinkingDemo/MobileDeepLinkingDemo-Info.plist"; 452 | LIBRARY_SEARCH_PATHS = ( 453 | "$(inherited)", 454 | "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/MobileDeepLinking-gfuxzmkstjruakdecxfaohfnfwhq/Build/Products/Debug-iphoneos", 455 | ); 456 | PRODUCT_NAME = "$(TARGET_NAME)"; 457 | WRAPPER_EXTENSION = app; 458 | }; 459 | name = Debug; 460 | }; 461 | AABF8E6B188F2D3400E35A09 /* Release */ = { 462 | isa = XCBuildConfiguration; 463 | buildSettings = { 464 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 465 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 466 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 467 | GCC_PREFIX_HEADER = "MobileDeepLinkingDemo/MobileDeepLinkingDemo-Prefix.pch"; 468 | INFOPLIST_FILE = "MobileDeepLinkingDemo/MobileDeepLinkingDemo-Info.plist"; 469 | LIBRARY_SEARCH_PATHS = ( 470 | "$(inherited)", 471 | "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/MobileDeepLinking-gfuxzmkstjruakdecxfaohfnfwhq/Build/Products/Debug-iphoneos", 472 | ); 473 | PRODUCT_NAME = "$(TARGET_NAME)"; 474 | WRAPPER_EXTENSION = app; 475 | }; 476 | name = Release; 477 | }; 478 | AABF8E6D188F2D3400E35A09 /* Debug */ = { 479 | isa = XCBuildConfiguration; 480 | buildSettings = { 481 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 482 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/MobileDeepLinkingDemo.app/MobileDeepLinkingDemo"; 483 | FRAMEWORK_SEARCH_PATHS = ( 484 | "$(SDKROOT)/Developer/Library/Frameworks", 485 | "$(inherited)", 486 | "$(DEVELOPER_FRAMEWORKS_DIR)", 487 | ); 488 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 489 | GCC_PREFIX_HEADER = "MobileDeepLinkingDemo/MobileDeepLinkingDemo-Prefix.pch"; 490 | GCC_PREPROCESSOR_DEFINITIONS = ( 491 | "DEBUG=1", 492 | "$(inherited)", 493 | ); 494 | INFOPLIST_FILE = "MobileDeepLinkingDemoTests/MobileDeepLinkingDemoTests-Info.plist"; 495 | PRODUCT_NAME = "$(TARGET_NAME)"; 496 | TEST_HOST = "$(BUNDLE_LOADER)"; 497 | WRAPPER_EXTENSION = xctest; 498 | }; 499 | name = Debug; 500 | }; 501 | AABF8E6E188F2D3400E35A09 /* Release */ = { 502 | isa = XCBuildConfiguration; 503 | buildSettings = { 504 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 505 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/MobileDeepLinkingDemo.app/MobileDeepLinkingDemo"; 506 | FRAMEWORK_SEARCH_PATHS = ( 507 | "$(SDKROOT)/Developer/Library/Frameworks", 508 | "$(inherited)", 509 | "$(DEVELOPER_FRAMEWORKS_DIR)", 510 | ); 511 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 512 | GCC_PREFIX_HEADER = "MobileDeepLinkingDemo/MobileDeepLinkingDemo-Prefix.pch"; 513 | INFOPLIST_FILE = "MobileDeepLinkingDemoTests/MobileDeepLinkingDemoTests-Info.plist"; 514 | PRODUCT_NAME = "$(TARGET_NAME)"; 515 | TEST_HOST = "$(BUNDLE_LOADER)"; 516 | WRAPPER_EXTENSION = xctest; 517 | }; 518 | name = Release; 519 | }; 520 | /* End XCBuildConfiguration section */ 521 | 522 | /* Begin XCConfigurationList section */ 523 | AABF8E29188F2D3300E35A09 /* Build configuration list for PBXProject "MobileDeepLinkingDemo" */ = { 524 | isa = XCConfigurationList; 525 | buildConfigurations = ( 526 | AABF8E67188F2D3400E35A09 /* Debug */, 527 | AABF8E68188F2D3400E35A09 /* Release */, 528 | ); 529 | defaultConfigurationIsVisible = 0; 530 | defaultConfigurationName = Release; 531 | }; 532 | AABF8E69188F2D3400E35A09 /* Build configuration list for PBXNativeTarget "MobileDeepLinkingDemo" */ = { 533 | isa = XCConfigurationList; 534 | buildConfigurations = ( 535 | AABF8E6A188F2D3400E35A09 /* Debug */, 536 | AABF8E6B188F2D3400E35A09 /* Release */, 537 | ); 538 | defaultConfigurationIsVisible = 0; 539 | defaultConfigurationName = Release; 540 | }; 541 | AABF8E6C188F2D3400E35A09 /* Build configuration list for PBXNativeTarget "MobileDeepLinkingDemoTests" */ = { 542 | isa = XCConfigurationList; 543 | buildConfigurations = ( 544 | AABF8E6D188F2D3400E35A09 /* Debug */, 545 | AABF8E6E188F2D3400E35A09 /* Release */, 546 | ); 547 | defaultConfigurationIsVisible = 0; 548 | defaultConfigurationName = Release; 549 | }; 550 | /* End XCConfigurationList section */ 551 | }; 552 | rootObject = AABF8E26188F2D3300E35A09 /* Project object */; 553 | } 554 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo.xcodeproj/xcshareddata/xcschemes/MobileDeepLinkingDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | @interface AppDelegate : UIResponder 26 | 27 | @property(strong, nonatomic) UIWindow *window; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "AppDelegate.h" 24 | #import "NonIBViewController.h" 25 | #import 26 | 27 | @implementation AppDelegate 28 | 29 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 30 | { 31 | [[MobileDeepLinking sharedInstance] registerHandlerWithName:@"mutatorHandler" handler:^void(NSDictionary *params) 32 | { 33 | NSLog(@"mutatorHandler:"); 34 | for (NSString *param in params) 35 | { 36 | NSLog(@"%@: %@", param, [params objectForKey:param]); 37 | } 38 | [params setValue:@"handlerValue" forKey:@"handlerName"]; 39 | }]; 40 | 41 | [[MobileDeepLinking sharedInstance] registerHandlerWithName:@"myHandler" handler:^void(NSDictionary *params) 42 | { 43 | NSLog(@"myHandler:"); 44 | for (NSString *param in params) 45 | { 46 | NSLog(@"%@: %@", param, [params objectForKey:param]); 47 | } 48 | }]; 49 | 50 | [[MobileDeepLinking sharedInstance] registerHandlerWithName:@"routeToNonNibView" handler:^void(NSDictionary *params) 51 | { 52 | NonIBViewController *nonIBViewController = [[NonIBViewController alloc] init]; 53 | UITabBarController *tabBarController = (UITabBarController *) self.window.rootViewController; 54 | [tabBarController setSelectedIndex:0]; 55 | [(UINavigationController *) [tabBarController.viewControllers objectAtIndex:0] pushViewController:nonIBViewController animated:YES]; 56 | }]; 57 | 58 | // Override point for customization after application launch. 59 | return YES; 60 | } 61 | 62 | - (void)applicationWillResignActive:(UIApplication *)application 63 | { 64 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 65 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 66 | } 67 | 68 | - (void)applicationDidEnterBackground:(UIApplication *)application 69 | { 70 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 71 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 72 | } 73 | 74 | - (void)applicationWillEnterForeground:(UIApplication *)application 75 | { 76 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 77 | } 78 | 79 | - (void)applicationDidBecomeActive:(UIApplication *)application 80 | { 81 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 82 | } 83 | 84 | - (void)applicationWillTerminate:(UIApplication *)application 85 | { 86 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 87 | } 88 | 89 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation 90 | { 91 | NSLog(@"scheme: %@", [url scheme]); 92 | NSLog(@"host: %@", [url host]); 93 | NSLog(@"port: %@", [url port]); 94 | NSLog(@"path: %@", [url path]); 95 | NSLog(@"path components: %@", [url pathComponents]); 96 | NSLog(@"parameterString: %@", [url parameterString]); 97 | NSLog(@"query: %@", [url query]); 98 | NSLog(@"fragment: %@", [url fragment]); 99 | 100 | [[MobileDeepLinking sharedInstance] routeUsingUrl:url]; 101 | return YES; 102 | } 103 | 104 | @end 105 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/Base.lproj/Main_iPad.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 26 | 27 | 28 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/Base.lproj/Main_iPhone.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/DataViewController.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | @interface DataViewController : UIViewController 26 | 27 | @property(strong, nonatomic) IBOutlet UILabel *dataLabel; 28 | @property(strong, nonatomic) id dataObject; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/DataViewController.m: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "DataViewController.h" 24 | 25 | @interface DataViewController () 26 | 27 | @end 28 | 29 | @implementation DataViewController 30 | 31 | - (void)viewDidLoad 32 | { 33 | [super viewDidLoad]; 34 | // Do any additional setup after loading the view, typically from a nib. 35 | } 36 | 37 | - (void)didReceiveMemoryWarning 38 | { 39 | [super didReceiveMemoryWarning]; 40 | // Dispose of any resources that can be recreated. 41 | } 42 | 43 | - (void)viewWillAppear:(BOOL)animated 44 | { 45 | [super viewWillAppear:animated]; 46 | self.dataLabel.text = [self.dataObject description]; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "ipad", 20 | "size" : "29x29", 21 | "scale" : "1x" 22 | }, 23 | { 24 | "idiom" : "ipad", 25 | "size" : "29x29", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "ipad", 30 | "size" : "40x40", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "40x40", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "76x76", 41 | "scale" : "1x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "76x76", 46 | "scale" : "2x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "orientation" : "portrait", 20 | "idiom" : "ipad", 21 | "extent" : "full-screen", 22 | "minimum-system-version" : "7.0", 23 | "scale" : "1x" 24 | }, 25 | { 26 | "orientation" : "landscape", 27 | "idiom" : "ipad", 28 | "extent" : "full-screen", 29 | "minimum-system-version" : "7.0", 30 | "scale" : "1x" 31 | }, 32 | { 33 | "orientation" : "portrait", 34 | "idiom" : "ipad", 35 | "extent" : "full-screen", 36 | "minimum-system-version" : "7.0", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "orientation" : "landscape", 41 | "idiom" : "ipad", 42 | "extent" : "full-screen", 43 | "minimum-system-version" : "7.0", 44 | "scale" : "2x" 45 | } 46 | ], 47 | "info" : { 48 | "version" : 1, 49 | "author" : "xcode" 50 | } 51 | } -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/MobileDeepLinkingConfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging": "true", 3 | "defaultRoute": { 4 | "storyboard": { 5 | "iPhone" : "Main_iPhone", 6 | "iPad" : "Main_iPad" 7 | }, 8 | "storyboard": "Main_iPhone", 9 | "class": "DataViewController", 10 | "identifier": "DataViewController" 11 | }, 12 | "routes": { 13 | "data" : { 14 | "storyboard": { 15 | "iPhone" : "Main_iPhone", 16 | "iPad" : "Main_iPad" 17 | }, 18 | "identifier": "storyBoardViewController" 19 | }, 20 | "data/:dataId": { 21 | "storyboard": { 22 | "iPhone" : "Main_iPhone", 23 | "iPad" : "Main_iPad" 24 | }, 25 | "identifier": "storyBoardViewController", 26 | "handlers": ["myHandler"], 27 | "routeParameters": { 28 | "utmSource": { 29 | "required": "true" 30 | } 31 | } 32 | }, 33 | "regex/:dataId": { 34 | "storyboard": { 35 | "iPhone" : "Main_iPhone", 36 | "iPad" : "Main_iPad" 37 | }, 38 | "identifier": "storyBoardViewController", 39 | "handlers": ["myHandler"], 40 | "routeParameters": { 41 | "dataId": { 42 | "required": "true", 43 | "regex": "[0-9]" 44 | }, 45 | "utmSource": { 46 | "required": "false" 47 | } 48 | } 49 | }, 50 | "sale/:saleId": { 51 | "identifier": "ViewControllerWithNib", 52 | "class": "ViewControllerWithNib", 53 | "handlers": ["mutatorHandler", "myHandler"] 54 | }, 55 | "product": { 56 | "class": "NonIBViewController" 57 | }, 58 | "handler": { 59 | "handlers": ["routeToNonNibView"] 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/MobileDeepLinkingDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.mobiledeeplinking.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleURLTypes 24 | 25 | 26 | CFBundleTypeRole 27 | Editor 28 | CFBundleURLName 29 | com.mobiledeeplinking 30 | CFBundleURLSchemes 31 | 32 | mdldemo 33 | 34 | 35 | 36 | CFBundleVersion 37 | 1.0 38 | LSRequiresIPhoneOS 39 | 40 | UIMainStoryboardFile 41 | Main_iPhone 42 | UIMainStoryboardFile~ipad 43 | Main_iPad 44 | UIRequiredDeviceCapabilities 45 | 46 | armv7 47 | 48 | UISupportedInterfaceOrientations 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationLandscapeLeft 52 | UIInterfaceOrientationLandscapeRight 53 | 54 | UISupportedInterfaceOrientations~ipad 55 | 56 | UIInterfaceOrientationPortrait 57 | UIInterfaceOrientationPortraitUpsideDown 58 | UIInterfaceOrientationLandscapeLeft 59 | UIInterfaceOrientationLandscapeRight 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/MobileDeepLinkingDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | 15 | #import 16 | #import 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/NonIBViewController.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | @interface NonIBViewController : UIViewController 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/NonIBViewController.m: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "NonIBViewController.h" 24 | 25 | @interface NonIBViewController () 26 | 27 | @end 28 | 29 | @implementation NonIBViewController 30 | 31 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 32 | { 33 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 34 | if (self) 35 | { 36 | // Custom initialization 37 | } 38 | return self; 39 | } 40 | 41 | - (void)loadView 42 | { 43 | CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame]; 44 | UIView *contentView = [[UIView alloc] initWithFrame:applicationFrame]; 45 | contentView.backgroundColor = [UIColor whiteColor]; 46 | self.view = contentView; 47 | 48 | UILabel *label = [[UILabel alloc] init]; 49 | label.numberOfLines = 2; 50 | [label setText:[NSString stringWithFormat:@"View Controller Without Storyboard or Nib."]]; 51 | 52 | [label setFrame:CGRectMake((self.view.frame.size.width / 2), 53 | (self.view.frame.size.height / 2), 54 | 300, 55 | 250)]; 56 | [label setCenter:self.view.center]; 57 | label.textAlignment = NSTextAlignmentCenter; 58 | [self.view addSubview:label]; 59 | } 60 | 61 | - (void)viewDidLoad 62 | { 63 | [super viewDidLoad]; 64 | // Do any additional setup after loading the view. 65 | 66 | } 67 | 68 | - (void)didReceiveMemoryWarning 69 | { 70 | [super didReceiveMemoryWarning]; 71 | // Dispose of any resources that can be recreated. 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/StoryBoardViewController.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | 26 | @interface StoryBoardViewController : UIViewController 27 | 28 | @property(nonatomic, strong) id dataId; 29 | @property(nonatomic, strong) id utmSource; 30 | @end -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/StoryBoardViewController.m: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "StoryBoardViewController.h" 24 | 25 | 26 | @implementation StoryBoardViewController 27 | { 28 | 29 | } 30 | 31 | @synthesize dataId; 32 | @synthesize utmSource; 33 | 34 | - (void)viewDidLoad 35 | { 36 | [super viewDidLoad]; 37 | NSLog(@"%@", dataId); 38 | // Do any additional setup after loading the view, typically from a nib. 39 | } 40 | 41 | - (void)didReceiveMemoryWarning 42 | { 43 | [super didReceiveMemoryWarning]; 44 | // Dispose of any resources that can be recreated. 45 | } 46 | 47 | - (void)viewWillAppear:(BOOL)animated 48 | { 49 | [super viewWillAppear:animated]; 50 | } 51 | @end -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/ViewControllerWithNib.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | @interface ViewControllerWithNib : UIViewController 26 | { 27 | IBOutlet UILabel *label; 28 | } 29 | 30 | @property(retain, nonatomic) IBOutlet UILabel *label; 31 | @property(nonatomic, strong) id saleId; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/ViewControllerWithNib.m: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "ViewControllerWithNib.h" 24 | 25 | @interface ViewControllerWithNib () 26 | 27 | @end 28 | 29 | @implementation ViewControllerWithNib 30 | 31 | @synthesize saleId; 32 | @synthesize label; 33 | 34 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 35 | { 36 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 37 | if (self) 38 | { 39 | // Custom initialization 40 | } 41 | return self; 42 | } 43 | 44 | - (void)viewDidLoad 45 | { 46 | [super viewDidLoad]; 47 | // Do any additional setup after loading the view from its nib. 48 | 49 | [label setText:saleId]; 50 | } 51 | 52 | - (void)didReceiveMemoryWarning 53 | { 54 | [super didReceiveMemoryWarning]; 55 | // Dispose of any resources that can be recreated. 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/ViewControllerWithNib.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 25 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // MobileDeepLinkingDemo 4 | // 5 | // Created by Ethan on 1/21/14. 6 | // Copyright (c) 2014 mobiledeeplinking. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | @autoreleasepool 14 | { 15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemoTests/MobileDeepLinkingDemoTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.mobiledeeplinking.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemoTests/MobileDeepLinkingDemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // MobileDeepLinkingDemoTests.m 3 | // MobileDeepLinkingDemoTests 4 | // 5 | // Created by Ethan on 1/21/14. 6 | // Copyright (c) 2014 mobiledeeplinking. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MobileDeepLinkingDemoTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation MobileDeepLinkingDemoTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /MobileDeepLinkingDemo/MobileDeepLinkingDemoTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '5.0' 2 | pod 'OCMock', '~> 2.2.2' 3 | pod 'Expecta', '~> 0.2.3' 4 | 5 | link_with 'MobileDeepLinkingTests' 6 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Expecta (0.2.3) 3 | - OCMock (2.2.2) 4 | 5 | DEPENDENCIES: 6 | - Expecta (~> 0.2.3) 7 | - OCMock (~> 2.2.2) 8 | 9 | SPEC CHECKSUMS: 10 | Expecta: dbc4a27fabb853bdd2e907e33f11ee43a9a47d0c 11 | OCMock: ffba68873fd32cfd35d885bddad23bfa816da4a3 12 | 13 | COCOAPODS: 0.29.0 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This repository is no longer maintained. 2 | 3 | Issue reports and pull requests will not be attended. 4 | 5 | # MobileDeepLinking [![Build Status](https://travis-ci.org/mobiledeeplinking/mobiledeeplinking-ios.png?branch=master)](https://travis-ci.org/mobiledeeplinking/mobiledeeplinking-ios) 6 | 7 | This project is the iOS library component of the MobileDeepLinking specification, the industry standard for mobile application deeplinking. This specification and accompanying libraries simplify and reduce implementation time for deep links as well as provide flexible and powerful features for routing to custom behavior. 8 | 9 | ## Features 10 | 11 | Given a configuration file (`MobileDeepLinkingConfig.json`), this library provides an app the ability to route incoming deeplinks to view controllers or custom logic. It has the ability to automatically instantiate and push view controllers onto the navigation controller, as well the ability to register callback handlers that are executed when matching a deeplink. 12 | 13 | ### View Routing 14 | 15 | When a view is defined in the configuration file, the library will instantiate the viewController as appropriate and then attempt to push it to the appropriate navigation controller. The route parameters defined in the configuration file (path and query parameters) will be set on this viewController. 16 | 17 | Three types of viewControllers are supported. They are listed below with the appropriate json configuration settings: 18 | 19 | 1. Storyboard - requires `storyboard` (storyboard name) and `identifier` (view storyboard identifier) attributes 20 | 2. Xib - requires `identifier` (xib name) and `class` (viewController class name) attributes. 21 | 3. Non Interface Builder View Controller - requires `class` (viewController class name) attribute. 22 | 23 | 24 | ### Handlers 25 | 26 | There may be cases where you need to set up a view before displaying it. This functionality is supported through the use of custom handlers. In the `didFinishLaunchingWithOptions` method in your AppDelegate, you can register blocks (essentially callback functions) that will be executed when an associated route is matched. This association takes place in the configuration json. 27 | 28 | These handlers are provided with an NSDictionary with all route parameters found in the deeplink. They can modify the contents of this dictionary, which will be forwarded on to the next handler in the handlers array. Handlers can be reused across multiple routes and can be used in conjunction with view instantiation or entirely on their own. 29 | 30 | ## Compatibility 31 | 32 | This library was developed using ARC and supports iOS 5 and above on all architectures. 33 | 34 | 35 | ## Build 36 | 37 | This library follows the iOS Framework build process laid out [here](https://github.com/jverkoey/iOS-Framework). The library can be found in the releases/ folder. It is also available through CocoaPods. 38 | 39 | To build from source: 40 | 41 | 1. Build the `MobileDeepLinking-iOS` scheme. 42 | 2. Build the `Framework` scheme. 43 | 3. Expand the `Products` folder in Xcode, right click the .a file, and click "Show in Finder". Within this folder you will see your `.framework` folder. This is the built framework file that can be dropped into other projects. 44 | 45 | 46 | ## Installation 47 | 48 | #### Required 49 | 50 | Create a `MobileDeepLinkingConfig.json` file in your project with your desired routes and options. See demo app and spec for examples. 51 | 52 | Insert the following line into the `- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation` method in your AppDelegate: 53 | 54 | [[MobileDeepLinking sharedInstance] routeUsingUrl:url]; 55 | 56 | #### Optional 57 | 58 | Register Custom Handlers (if desired) in your AppDelegate's `didFinishLaunchingWithOptions` method: 59 | 60 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 61 | { 62 | [[MobileDeepLinking sharedInstance] registerHandlerWithName:@"exampleHandler" handler:^void(NSDictionary *params) 63 | { 64 | NSLog(@"exampleHandler"); 65 | }]; 66 | } 67 | 68 | ## Run Unit Tests 69 | 70 | This assumes you have [CocoaPods](http://cocoapods.org/) installed. 71 | 72 | 1. Run `pod install` 73 | 2. Open `MobileDeepLinking.xcworkspace` 74 | 3. Test using 'MobileDeepLinking-iOS' scheme. 75 | 76 | ## Demo App 77 | 78 | Part of the `MobileDeepLinking.xcworkspace` includes `MobileDeepLinkingDemo`. This is a demo application that provides an example implementation of the `MobileDeepLinkingConfig.json` file, along with several custom handlers that demonstrate how to route to client-specified functionality. It also provides example routing to a storyboard based view, a xib based view, and a view without any Interface Builder elements. 79 | 80 | ## License 81 | 82 | Copyright 2014 MobileDeepLinking.org and other contributors 83 | http://mobiledeeplinking.org 84 | 85 | Permission is hereby granted, free of charge, to any person obtaining 86 | a copy of this software and associated documentation files (the 87 | "Software"), to deal in the Software without restriction, including 88 | without limitation the rights to use, copy, modify, merge, publish, 89 | distribute, sublicense, and/or sell copies of the Software, and to 90 | permit persons to whom the Software is furnished to do so, subject to 91 | the following conditions: 92 | 93 | The above copyright notice and this permission notice shall be 94 | included in all copies or substantial portions of the Software. 95 | 96 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 97 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 98 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 99 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 100 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 101 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 102 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 103 | -------------------------------------------------------------------------------- /releases/0.1.0/MobileDeepLinking.framework/Headers: -------------------------------------------------------------------------------- 1 | Versions/Current/Headers -------------------------------------------------------------------------------- /releases/0.1.0/MobileDeepLinking.framework/MobileDeepLinking: -------------------------------------------------------------------------------- 1 | Versions/Current/MobileDeepLinking -------------------------------------------------------------------------------- /releases/0.1.0/MobileDeepLinking.framework/Versions/A/Headers/MobileDeepLinking.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | #import 25 | 26 | @interface MobileDeepLinking : NSObject 27 | 28 | + (id)sharedInstance; 29 | 30 | - (void)registerHandlerWithName:(NSString *)handlerName handler:(void (^)(NSDictionary *))handlerFunction; 31 | 32 | - (void)routeUsingUrl:(NSURL *)deeplink; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /releases/0.1.0/MobileDeepLinking.framework/Versions/A/MobileDeepLinking: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mobiledeeplinking/mobiledeeplinking-ios/08451fb87bec0dcb1d34081faa30a4baa820a981/releases/0.1.0/MobileDeepLinking.framework/Versions/A/MobileDeepLinking -------------------------------------------------------------------------------- /releases/0.1.0/MobileDeepLinking.framework/Versions/Current: -------------------------------------------------------------------------------- 1 | A -------------------------------------------------------------------------------- /releases/0.1.1/MobileDeepLinking.framework/Headers: -------------------------------------------------------------------------------- 1 | Versions/Current/Headers -------------------------------------------------------------------------------- /releases/0.1.1/MobileDeepLinking.framework/MobileDeepLinking: -------------------------------------------------------------------------------- 1 | Versions/Current/MobileDeepLinking -------------------------------------------------------------------------------- /releases/0.1.1/MobileDeepLinking.framework/Versions/A/Headers/MobileDeepLinking.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | #import 25 | 26 | @interface MobileDeepLinking : NSObject 27 | 28 | + (id)sharedInstance; 29 | 30 | - (void)registerHandlerWithName:(NSString *)handlerName handler:(void (^)(NSDictionary *))handlerFunction; 31 | 32 | - (void)routeUsingUrl:(NSURL *)deeplink; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /releases/0.1.1/MobileDeepLinking.framework/Versions/A/MobileDeepLinking: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mobiledeeplinking/mobiledeeplinking-ios/08451fb87bec0dcb1d34081faa30a4baa820a981/releases/0.1.1/MobileDeepLinking.framework/Versions/A/MobileDeepLinking -------------------------------------------------------------------------------- /releases/0.1.1/MobileDeepLinking.framework/Versions/Current: -------------------------------------------------------------------------------- 1 | A -------------------------------------------------------------------------------- /releases/0.2.0/MobileDeepLinking.framework/Headers: -------------------------------------------------------------------------------- 1 | Versions/Current/Headers -------------------------------------------------------------------------------- /releases/0.2.0/MobileDeepLinking.framework/MobileDeepLinking: -------------------------------------------------------------------------------- 1 | Versions/Current/MobileDeepLinking -------------------------------------------------------------------------------- /releases/0.2.0/MobileDeepLinking.framework/Versions/A/Headers/MobileDeepLinking.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 by MobileDeepLinking.org 2 | // 3 | // Permission is hereby granted, free of charge, to any 4 | // person obtaining a copy of this software and 5 | // associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, 8 | // publish, distribute, sublicense, and/or sell copies of the 9 | // Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall 13 | // be included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | #import 25 | 26 | @interface MobileDeepLinking : NSObject 27 | 28 | + (id)sharedInstance; 29 | 30 | - (void)registerHandlerWithName:(NSString *)handlerName handler:(void (^)(NSDictionary *))handlerFunction; 31 | 32 | - (void)routeUsingUrl:(NSURL *)deeplink; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /releases/0.2.0/MobileDeepLinking.framework/Versions/A/MobileDeepLinking: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mobiledeeplinking/mobiledeeplinking-ios/08451fb87bec0dcb1d34081faa30a4baa820a981/releases/0.2.0/MobileDeepLinking.framework/Versions/A/MobileDeepLinking -------------------------------------------------------------------------------- /releases/0.2.0/MobileDeepLinking.framework/Versions/Current: -------------------------------------------------------------------------------- 1 | A --------------------------------------------------------------------------------