├── images └── WAAppRouting.png ├── SimpleExample ├── Podfile ├── SimpleExample.xcodeproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── SimpleExample.xcworkspace │ └── contents.xcworkspacedata ├── SimpleExample │ ├── WAListDetailViewController.h │ ├── WAListDetailExtraViewController.h │ ├── WABaseDetailViewController.h │ ├── AppDelegate.h │ ├── main.m │ ├── WAListViewController.h │ ├── WABaseViewController.h │ ├── WAListDetailExtraViewController.m │ ├── WABaseViewController.m │ ├── WABaseDetailViewController.m │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── WAListDetailViewController.m │ ├── Info.plist │ ├── WAListViewController.m │ ├── Base.lproj │ │ └── LaunchScreen.xib │ └── AppDelegate.m ├── Podfile.lock └── SimpleExampleTests │ ├── Info.plist │ └── SimpleExampleTests.m ├── MoreComplexExample ├── Podfile ├── MoreComplexExample.xcodeproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── MoreComplexExample.xcworkspace │ └── contents.xcworkspacedata ├── MoreComplexExample │ ├── WAList1ViewController.h │ ├── WAModalViewController.h │ ├── WAList2ViewController.h │ ├── WAList1DetailViewController.h │ ├── WAList2DetailViewController.h │ ├── WAList1DetailExtraViewController.h │ ├── WAList1Subpath1DetailController.h │ ├── WAList1Subpath2DetailController.h │ ├── WABaseDetailViewController.h │ ├── AppDelegate.h │ ├── main.m │ ├── WABaseTableViewController.h │ ├── WABaseViewController.h │ ├── WABaseViewController.m │ ├── WAList1Subpath1DetailController.m │ ├── WAList1Subpath2DetailController.m │ ├── WABaseDetailViewController.m │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── WAList1DetailViewController.m │ ├── WABaseTableViewController.m │ ├── WAModalViewController.m │ ├── Info.plist │ ├── WAList2ViewController.m │ ├── WAList1ViewController.m │ ├── WAList2DetailViewController.m │ ├── WAList1DetailExtraViewController.m │ └── Base.lproj │ │ └── LaunchScreen.xib ├── Podfile.lock └── MoreComplexExampleTests │ ├── Info.plist │ └── MoreComplexExampleTests.m ├── SimpleExampleParameters ├── Podfile ├── SimpleExampleParameters.xcodeproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── SimpleExampleParameters.xcworkspace │ └── contents.xcworkspacedata ├── SimpleExampleParameters │ ├── WAListDetailViewController.h │ ├── WAListDetailExtraViewController.h │ ├── WABaseDetailViewController.h │ ├── AppDelegate.h │ ├── main.m │ ├── WAListViewController.h │ ├── ArticleAppLinkParameters+Additions.h │ ├── WAListDetailExtraViewController.m │ ├── WABaseViewController.h │ ├── ArticleAppLinkParameters.h │ ├── ArticleAppLinkParameters.m │ ├── ArticleAppLinkParameters+Additions.m │ ├── WABaseViewController.m │ ├── WABaseDetailViewController.m │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── WAListDetailViewController.m │ ├── Info.plist │ ├── WAListViewController.m │ ├── Base.lproj │ │ └── LaunchScreen.xib │ └── AppDelegate.m ├── Podfile.lock └── SimpleExampleParametersTests │ ├── Info.plist │ └── SimpleExampleParametersTests.m ├── PPRevealSample ├── Podfile ├── PPRevealSample.xcodeproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── PPRevealSample.xcworkspace │ └── contents.xcworkspacedata ├── PPRevealSample │ ├── WAModalViewController.h │ ├── WAList1ViewController.h │ ├── WAList2ViewController.h │ ├── WALeftMenuViewController.h │ ├── WAList1DetailViewController.h │ ├── WAList2DetailViewController.h │ ├── WAList1DetailExtraViewController.h │ ├── WABaseDetailViewController.h │ ├── AppDelegate.h │ ├── main.m │ ├── WABaseTableViewController.h │ ├── WAList1DetailExtraViewController.m │ ├── PPRevealSideViewController+WAAppRoutingContainerPresentationProtocol.h │ ├── WABaseViewController.h │ ├── WABaseViewController.m │ ├── WABaseDetailViewController.m │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── WAList1DetailViewController.m │ ├── WAList2ViewController.m │ ├── WABaseTableViewController.m │ ├── WAList1ViewController.m │ ├── WAModalViewController.m │ ├── Info.plist │ ├── WALeftMenuViewController.m │ ├── WAList2DetailViewController.m │ ├── PPRevealSideViewController+WAAppRoutingContainerPresentationProtocol.m │ ├── Base.lproj │ │ └── LaunchScreen.xib │ └── AppDelegate.m ├── PPRevealSampleTests │ ├── Info.plist │ └── PPRevealSampleTests.m └── Podfile.lock ├── WAAppRoutingTests ├── Podfile ├── WAAppRoutingTests.xcodeproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── WAAppRoutingTests.xcworkspace │ └── contents.xcworkspacedata ├── WAAppRoutingTests │ ├── ViewController.h │ ├── AppDelegate.h │ ├── main.m │ ├── ViewController.m │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.xib │ ├── Info.plist │ └── AppDelegate.m ├── Podfile.lock └── WAAppRoutingTestsTests │ └── Info.plist ├── .gitignore ├── Files ├── NSString+WAAdditions.h ├── NSMutableDictionary+WAAppRoutingParameters.h ├── WAAppRouting.h ├── NSURL+WAAdditions.h ├── WAAppRouteMatcher.h ├── WAAppRouter+WADefaultRouter.h ├── UIViewController+WAAppLinkParameters.h ├── NSURL+WAAdditions.m ├── UINavigationController+WAAdditions.h ├── WAAppRouterTargetControllerProtocol.h ├── UITabBarController+WAAppRoutingContainerPresentationProtocol.h ├── WAAppMacros.h ├── UITabBarController+WAAppRoutingContainerPresentationProtocol.m ├── UINavigationController+WAAdditions.m ├── WAAppRouter+WADefaultRouter.m ├── WAAppRouterMatcherProtocol.h ├── NSString+WAAdditions.m ├── WAAppLink.m ├── WAAppRoutingContainerPresentationProtocol.h ├── WARoutePattern.h ├── WAAppRouteHandler.h ├── WAAppLink.h ├── WAAppRouter.h ├── WAAppRouteHandlerProtocol.h ├── WAAppRouteMatcher.m ├── NSMutableDictionary+WAAppRoutingParameters.m ├── WAAppRouterParametersProtocol.h ├── UIViewController+WAAppLinkParameters.m ├── WAAppRouter.m ├── WAAppLinkParameters.h ├── WARoutePattern.m ├── WAAppRouteEntity.h ├── WAAppRouteRegistrar.h └── WAAppRouteEntity.m ├── LICENSE ├── WAAppRouting.podspec └── CHANGELOG.md /images/WAAppRouting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wasappli/WAAppRouting/HEAD/images/WAAppRouting.png -------------------------------------------------------------------------------- /SimpleExample/Podfile: -------------------------------------------------------------------------------- 1 | pod 'PureLayout' 2 | pod 'RZNotificationView' 3 | pod 'WAAppRouting', :path => '../WAAppRouting.podspec' -------------------------------------------------------------------------------- /MoreComplexExample/Podfile: -------------------------------------------------------------------------------- 1 | pod 'PureLayout' 2 | pod 'RZNotificationView' 3 | pod 'WAAppRouting', :path => '../WAAppRouting.podspec' -------------------------------------------------------------------------------- /SimpleExampleParameters/Podfile: -------------------------------------------------------------------------------- 1 | pod 'PureLayout' 2 | pod 'RZNotificationView' 3 | pod 'WAAppRouting', :path => '../WAAppRouting.podspec' -------------------------------------------------------------------------------- /PPRevealSample/Podfile: -------------------------------------------------------------------------------- 1 | pod 'PureLayout' 2 | pod 'RZNotificationView' 3 | pod 'PPRevealSideViewController' 4 | 5 | pod 'WAAppRouting', :path => '../WAAppRouting.podspec' -------------------------------------------------------------------------------- /WAAppRoutingTests/Podfile: -------------------------------------------------------------------------------- 1 | pod 'WAAppRouting', :path => '../WAAppRouting.podspec' 2 | 3 | # Add Kiwi as an exclusive dependency for the WAAppRoutingTestsTests target 4 | target :WAAppRoutingTestsTests, :exclusive => true do 5 | pod 'Kiwi' 6 | end -------------------------------------------------------------------------------- /SimpleExample/SimpleExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WAAppRoutingTests/WAAppRoutingTests.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Various settings 2 | *.pbxuser 3 | !default.pbxuser 4 | *.mode1v3 5 | !default.mode1v3 6 | *.mode2v3 7 | !default.mode2v3 8 | *.perspectivev3 9 | !default.perspectivev3 10 | xcuserdata 11 | 12 | ## Other 13 | *.xccheckout 14 | *.moved-aside 15 | *.xcuserstate 16 | *.xcscmblueprint 17 | 18 | # CocoaPods 19 | Pods/ -------------------------------------------------------------------------------- /SimpleExample/SimpleExample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /WAAppRoutingTests/WAAppRoutingTests.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /WAAppRoutingTests/WAAppRoutingTests/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // WAAppRoutingTests 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Files/NSString+WAAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+WAAdditions.h 3 | // PPRevealSample 4 | // 5 | // Created by Marian Paul on 03/09/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | @interface NSString (WAAdditions) 12 | 13 | - (NSString *)waapp_stringByAddingPercentEscapes; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WAModalViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAModalViewController.h 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseViewController.h" 10 | 11 | @interface WAModalViewController : WABaseViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WAList1ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1ViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseTableViewController.h" 10 | 11 | @interface WAList1ViewController : WABaseTableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WAList1ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1ViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseTableViewController.h" 10 | 11 | @interface WAList1ViewController : WABaseTableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WAModalViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAModalViewController.h 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseViewController.h" 10 | 11 | @interface WAModalViewController : WABaseViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WAList2ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAList2ViewController.h 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseTableViewController.h" 10 | 11 | @interface WAList2ViewController : WABaseTableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WALeftMenuViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WALeftMenuViewController.h 3 | // PPRevealSample 4 | // 5 | // Created by Marian Paul on 20/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseTableViewController.h" 10 | 11 | @interface WALeftMenuViewController : WABaseTableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WAList2ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAList2ViewController.h 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseTableViewController.h" 10 | 11 | @interface WAList2ViewController : WABaseTableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /SimpleExample/SimpleExample/WAListDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1DetailViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseDetailViewController.h" 10 | 11 | @interface WAListDetailViewController : WABaseDetailViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WAList1DetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1DetailViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseDetailViewController.h" 10 | 11 | @interface WAList1DetailViewController : WABaseDetailViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WAList1DetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1DetailViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseDetailViewController.h" 10 | 11 | @interface WAList1DetailViewController : WABaseDetailViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WAList2DetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAList2DetailViewController.h 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseDetailViewController.h" 10 | 11 | @interface WAList2DetailViewController : WABaseDetailViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /SimpleExample/SimpleExample/WAListDetailExtraViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1DetailExtraViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseDetailViewController.h" 10 | 11 | @interface WAListDetailExtraViewController : WABaseDetailViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WAList2DetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAList2DetailViewController.h 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseDetailViewController.h" 10 | 11 | @interface WAList2DetailViewController : WABaseDetailViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WAList1DetailExtraViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1DetailExtraViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseDetailViewController.h" 10 | 11 | @interface WAList1DetailExtraViewController : WABaseDetailViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/WAListDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1DetailViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseDetailViewController.h" 10 | 11 | @interface WAListDetailViewController : WABaseDetailViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WAList1DetailExtraViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1DetailExtraViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseDetailViewController.h" 10 | 11 | @interface WAList1DetailExtraViewController : WABaseDetailViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WAList1Subpath1DetailController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1Subpath1DetailController.h 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 2015-08-22. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseDetailViewController.h" 10 | 11 | @interface WAList1Subpath1DetailController : WABaseDetailViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WAList1Subpath2DetailController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1Subpath2DetailController.h 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 2015-08-22. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseDetailViewController.h" 10 | 11 | @interface WAList1Subpath2DetailController : WABaseDetailViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/WAListDetailExtraViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1DetailExtraViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseDetailViewController.h" 10 | 11 | @interface WAListDetailExtraViewController : WABaseDetailViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WAAppRoutingTests/WAAppRoutingTests/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // WAAppRoutingTests 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WABaseDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseDetailViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseViewController.h" 10 | 11 | @interface WABaseDetailViewController : WABaseViewController 12 | 13 | @property (nonatomic, strong) UILabel *label; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /SimpleExample/SimpleExample/WABaseDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseDetailViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseViewController.h" 10 | 11 | @interface WABaseDetailViewController : WABaseViewController 12 | 13 | @property (nonatomic, strong) UILabel *label; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WABaseDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseDetailViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseViewController.h" 10 | 11 | @interface WABaseDetailViewController : WABaseViewController 12 | 13 | @property (nonatomic, strong) UILabel *label; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Files/NSMutableDictionary+WAAppRoutingParameters.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableDictionary+WAAppRoutingParameters.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 21/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | #import "WAAppRouterParametersProtocol.h" 11 | 12 | @interface NSMutableDictionary (WAAppRoutingParameters) 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /WAAppRoutingTests/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Kiwi (2.4.0) 3 | - WAAppRouting (0.0.5) 4 | 5 | DEPENDENCIES: 6 | - Kiwi 7 | - WAAppRouting (from `../WAAppRouting.podspec`) 8 | 9 | EXTERNAL SOURCES: 10 | WAAppRouting: 11 | :path: ../WAAppRouting.podspec 12 | 13 | SPEC CHECKSUMS: 14 | Kiwi: f49c9d54b28917df5928fe44968a39ed198cb8a8 15 | WAAppRouting: f678fa0dd488af81ee04aeab49e577f5ce187ae0 16 | 17 | COCOAPODS: 0.38.2 18 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // PPRevealSample 4 | // 5 | // Created by Marian Paul on 20/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | - (void)goTo:(NSString *)route, ...; 16 | 17 | @end 18 | 19 | -------------------------------------------------------------------------------- /SimpleExample/SimpleExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // SimpleExample 4 | // 5 | // Created by Marian Paul on 20/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | - (void)goTo:(NSString *)route, ...; 16 | 17 | @end 18 | 19 | -------------------------------------------------------------------------------- /SimpleExample/SimpleExample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SimpleExample 4 | // 5 | // Created by Marian Paul on 20/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/WABaseDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseDetailViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseViewController.h" 10 | 11 | @interface WABaseDetailViewController : WABaseViewController 12 | 13 | @property (nonatomic, strong) UILabel *label; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PPRevealSample 4 | // 5 | // Created by Marian Paul on 20/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | - (void)goTo:(NSString *)route, ...; 16 | 17 | @end 18 | 19 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SimpleExample/SimpleExample/WAListViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1ViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseViewController.h" 10 | 11 | @interface WAListViewController : WABaseViewController 12 | 13 | @property (nonatomic, strong) UITableView *tableView; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /WAAppRoutingTests/WAAppRoutingTests/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // WAAppRoutingTests 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WABaseTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseTableViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseViewController.h" 10 | 11 | @interface WABaseTableViewController : WABaseViewController 12 | 13 | @property (nonatomic, strong) UITableView *tableView; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // SimpleExampleParameters 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | - (void)goTo:(NSString *)route, ...; 16 | 17 | @end 18 | 19 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SimpleExampleParameters 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/WAListViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1ViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseViewController.h" 10 | 11 | @interface WAListViewController : WABaseViewController 12 | 13 | @property (nonatomic, strong) UITableView *tableView; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WABaseTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseTableViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseViewController.h" 10 | 11 | @interface WABaseTableViewController : WABaseViewController 12 | 13 | @property (nonatomic, strong) UITableView *tableView; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Files/WAAppRouting.h: -------------------------------------------------------------------------------- 1 | #import "WAAppRouter.h" 2 | #import "WAAppRouteHandler.h" 3 | #import "WAAppRouteRegistrar.h" 4 | #import "WAAppRouteMatcher.h" 5 | 6 | #import "WAAppRouterTargetControllerProtocol.h" 7 | #import "WAAppRoutingContainerPresentationProtocol.h" 8 | 9 | #import "WAAppLink.h" 10 | #import "WAAppRouteEntity.h" 11 | 12 | #import "NSMutableDictionary+WAAppRoutingParameters.h" 13 | #import "UIViewController+WAAppLinkParameters.h" 14 | #import "WAAppRouter+WADefaultRouter.h" -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/ArticleAppLinkParameters+Additions.h: -------------------------------------------------------------------------------- 1 | // 2 | // ArticleAppLinkParameters+Additions.h 3 | // SimpleExampleParameters 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "ArticleAppLinkParameters.h" 10 | 11 | @interface ArticleAppLinkParameters (Additions) 12 | 13 | - (NSString *)articleDetailQuery; 14 | - (NSString *)articleDetailExtraQuery; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /SimpleExample/SimpleExample/WABaseViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | #import 11 | 12 | #import "AppDelegate.h" 13 | 14 | @interface WABaseViewController : UIViewController 15 | 16 | @property (nonatomic, strong) id commonObject; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WABaseViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | #import 11 | #import "AppDelegate.h" 12 | 13 | @interface WABaseViewController : UIViewController 14 | 15 | @property (nonatomic, strong) id commonObject; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Files/NSURL+WAAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSURL+WAAdditions.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | @interface NSURL (WAAdditions) 12 | 13 | /** 14 | * Retrieve the query parameters from an URL. Do not decode the parameters 15 | * 16 | * @return a dictionary containing all the key values pairs from the URL 17 | */ 18 | - (NSDictionary *)waapp_queryParameters; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WABaseViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseViewController.h" 10 | 11 | @implementation WABaseViewController 12 | 13 | - (void)viewDidLoad { 14 | [super viewDidLoad]; 15 | self.view.backgroundColor = [UIColor whiteColor]; 16 | } 17 | 18 | - (void)reloadFromAppLinkRefresh { 19 | 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Files/WAAppRouteMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAAppRouteMatcher.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAAppRouterMatcherProtocol.h" 10 | 11 | /** 12 | * A class to match URLs against patterns. 13 | * By adopting the protocol, you can use any of the route matcher you want if your URLs have some rules not handled here etc. 14 | */ 15 | @interface WAAppRouteMatcher : NSObject 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /SimpleExample/SimpleExample/WAListDetailExtraViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1DetailExtraViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAListDetailExtraViewController.h" 10 | 11 | @implementation WAListDetailExtraViewController 12 | 13 | - (instancetype)init { 14 | self = [super init]; 15 | if (self) { 16 | self.title = @"Extra List"; 17 | } 18 | return self; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WAList1DetailExtraViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1DetailExtraViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAList1DetailExtraViewController.h" 10 | 11 | @implementation WAList1DetailExtraViewController 12 | 13 | - (instancetype)init { 14 | self = [super init]; 15 | if (self) { 16 | self.title = @"Extra List 1"; 17 | } 18 | return self; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WAList1Subpath1DetailController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1Subpath1DetailController.m 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 2015-08-22. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAList1Subpath1DetailController.h" 10 | 11 | @implementation WAList1Subpath1DetailController 12 | 13 | - (instancetype)init { 14 | self = [super init]; 15 | if (self) { 16 | self.title = @"Subpath 1"; 17 | } 18 | return self; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WAList1Subpath2DetailController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1Subpath2DetailController.m 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 2015-08-22. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAList1Subpath2DetailController.h" 10 | 11 | @implementation WAList1Subpath2DetailController 12 | 13 | - (instancetype)init { 14 | self = [super init]; 15 | if (self) { 16 | self.title = @"Subpath 2"; 17 | } 18 | return self; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/WAListDetailExtraViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1DetailExtraViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAListDetailExtraViewController.h" 10 | 11 | @implementation WAListDetailExtraViewController 12 | 13 | - (instancetype)init { 14 | self = [super init]; 15 | if (self) { 16 | self.title = @"Extra List"; 17 | } 18 | return self; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/WABaseViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | #import 11 | #import "AppDelegate.h" 12 | 13 | #import "ArticleAppLinkParameters.h" 14 | 15 | @interface WABaseViewController : UIViewController 16 | 17 | @property (nonatomic, strong) id commonObject; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/ArticleAppLinkParameters.h: -------------------------------------------------------------------------------- 1 | // 2 | // ArticleAppLinkParameters.h 3 | // SimpleExampleParameters 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ArticleAppLinkParameters : WAAppLinkParameters 12 | 13 | @property (nonatomic, strong) NSNumber *articleID; 14 | @property (nonatomic, strong) NSString *articleTitle; 15 | @property (nonatomic, strong) NSNumber *displayType; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Files/WAAppRouter+WADefaultRouter.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAAppRouter+WADefaultRouter.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 21/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAAppRouter.h" 10 | 11 | @interface WAAppRouter (WADefaultRouter) 12 | 13 | /** 14 | * Allocate and return a default configured router. You can define your own router with custom route matcher AND/OR route handler 15 | * 16 | * @return a fresh router which life is dedicated to help you 17 | */ 18 | + (instancetype) defaultRouter; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/PPRevealSideViewController+WAAppRoutingContainerPresentationProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // PPRevealSideViewController+WAAppRoutingContainerPresentationProtocol.h 3 | // PPRevealSample 4 | // 5 | // Created by Marian Paul on 20/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "PPRevealSideViewController.h" 10 | #import 11 | 12 | @interface PPRevealSideViewController (WAAppRoutingContainerPresentationProtocol) 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WABaseViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseViewController.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | #import 11 | #import 12 | 13 | #import "AppDelegate.h" 14 | 15 | @interface WABaseViewController : UIViewController 16 | 17 | @property (nonatomic, strong) id commonObject; 18 | 19 | - (void)addSideMenuButton; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/ArticleAppLinkParameters.m: -------------------------------------------------------------------------------- 1 | // 2 | // ArticleAppLinkParameters.m 3 | // SimpleExampleParameters 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "ArticleAppLinkParameters.h" 10 | 11 | @implementation ArticleAppLinkParameters 12 | 13 | - (NSDictionary *)mappingKeyProperty { 14 | return @{ 15 | @"articleID": @"articleID", 16 | @"article_title": @"articleTitle", 17 | @"display_type": @"displayType" 18 | }; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /SimpleExample/SimpleExample/WABaseViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseViewController.h" 10 | 11 | @implementation WABaseViewController 12 | 13 | - (void)viewDidLoad { 14 | [super viewDidLoad]; 15 | self.view.backgroundColor = [UIColor whiteColor]; 16 | } 17 | 18 | - (void)reloadFromAppLinkRefresh { 19 | // You can do something with self.appLink 20 | // But more important: with self.appLinkRoutingParameters which has merged route|query|default parameters 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /WAAppRoutingTests/WAAppRoutingTests/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // WAAppRoutingTests 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view, typically from a nib. 20 | } 21 | 22 | - (void)didReceiveMemoryWarning { 23 | [super didReceiveMemoryWarning]; 24 | // Dispose of any resources that can be recreated. 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/ArticleAppLinkParameters+Additions.m: -------------------------------------------------------------------------------- 1 | // 2 | // ArticleAppLinkParameters+Additions.m 3 | // SimpleExampleParameters 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "ArticleAppLinkParameters+Additions.h" 10 | 11 | @implementation ArticleAppLinkParameters (Additions) 12 | 13 | - (NSString *)articleDetailQuery { 14 | return [self queryStringWithWhiteList:@[@"articleID", @"articleTitle", @"displayType"]]; 15 | } 16 | 17 | - (NSString *)articleDetailExtraQuery { 18 | return [self queryStringWithWhiteList:@[@"articleID", @"articleTitle"]]; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Files/UIViewController+WAAppLinkParameters.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+WAAppLinkParameters.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 21/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | @class WAAppLink; 12 | @protocol WAAppRouterParametersProtocol; 13 | 14 | @interface UIViewController (WAAppLinkParameters) 15 | 16 | - (void)configureWithAppLink:(WAAppLink *)appLink defaultParameters:(id )defaultParameters allowedParameters:(NSArray *)allowedParameters; 17 | 18 | @property (nonatomic, strong) WAAppLink *appLink; 19 | @property (nonatomic, strong) id appLinkRoutingParameters; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Files/NSURL+WAAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSURL+WAAdditions.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "NSURL+WAAdditions.h" 10 | 11 | @implementation NSURL (WAAdditions) 12 | 13 | - (NSDictionary *)waapp_queryParameters { 14 | NSArray *parameters = [[self query] componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"=&"]]; 15 | NSMutableDictionary *keyValueParam = [NSMutableDictionary dictionary]; 16 | 17 | for (int i = 0; i < [parameters count]; i=i+2) { 18 | keyValueParam[parameters[i]] = parameters[i+1]; 19 | } 20 | return [keyValueParam copy]; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Files/UINavigationController+WAAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // UINavigationController+WAAdditions.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | @interface UINavigationController (WAAdditions) 12 | 13 | /** 14 | * Pop to the first controller of the class the navigation controller can have in its stack 15 | * If several controllers with the same class are in it, the first one starting from the end would be returned 16 | * 17 | * @param cClass the class to reach 18 | * @param animated pop with animation or not 19 | * 20 | * @return return the founded controller 21 | */ 22 | - (UIViewController *)waapp_popToFirstControllerOfClass:(Class)cClass animated:(BOOL)animated; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Files/WAAppRouterTargetControllerProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAAppRouterTargetControllerProtocol.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | #import "WAAppRouterParametersProtocol.h" 11 | 12 | @class WAAppLink; 13 | 14 | /** 15 | * @brief All controllers used with the route handler should conforms to this protocol in order to get configured with the app link 16 | */ 17 | @protocol WAAppRouterTargetControllerProtocol 18 | 19 | - (void)reloadFromAppLinkRefresh; 20 | 21 | @optional 22 | + (Class )appLinkParametersClass; 23 | - (void)waappRoutingDidDisplayController:(UIViewController *)controller withAppLink:(WAAppLink *)appLink; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Files/UITabBarController+WAAppRoutingContainerPresentationProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // UITabBarController+WAAppLinkContainerPresentationProtocol.h 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | #import "WAAppRoutingContainerPresentationProtocol.h" 11 | 12 | /** 13 | * @brief This category implements the @see `WAAppRoutingContainerPresentationProtocol` 14 | * This category acts as an example of how to use this protocol to get the container working (see the 'MoreComplexExample' project for tab bar and 'PPRevealSample' for a non Apple container) 15 | */ 16 | 17 | @interface UITabBarController (WAAppRoutingContainerPresentationProtocol) 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /SimpleExample/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - MOOMaskedIconView (0.1.0) 3 | - PPHelpMe (1.0.2) 4 | - PureLayout (3.0.1) 5 | - RZNotificationView (1.1.7): 6 | - MOOMaskedIconView (>= 0.1.0) 7 | - PPHelpMe (>= 1.0.0) 8 | - WAAppRouting (0.0.5) 9 | 10 | DEPENDENCIES: 11 | - PureLayout 12 | - RZNotificationView 13 | - WAAppRouting (from `../WAAppRouting.podspec`) 14 | 15 | EXTERNAL SOURCES: 16 | WAAppRouting: 17 | :path: ../WAAppRouting.podspec 18 | 19 | SPEC CHECKSUMS: 20 | MOOMaskedIconView: 42f22374cd15e81e65a1d67963374a961d94b909 21 | PPHelpMe: 243c40d2fad33ebdcc6b158c0db54893e0cc2d14 22 | PureLayout: f35f5384c9c4e4479df041dbe33ad7577b71ddfb 23 | RZNotificationView: 37b4a32e03a5f44a91ea76465f33313943a874d8 24 | WAAppRouting: f678fa0dd488af81ee04aeab49e577f5ce187ae0 25 | 26 | COCOAPODS: 0.38.2 27 | -------------------------------------------------------------------------------- /MoreComplexExample/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - MOOMaskedIconView (0.1.0) 3 | - PPHelpMe (1.0.2) 4 | - PureLayout (3.0.1) 5 | - RZNotificationView (1.1.7): 6 | - MOOMaskedIconView (>= 0.1.0) 7 | - PPHelpMe (>= 1.0.0) 8 | - WAAppRouting (0.0.5) 9 | 10 | DEPENDENCIES: 11 | - PureLayout 12 | - RZNotificationView 13 | - WAAppRouting (from `../WAAppRouting.podspec`) 14 | 15 | EXTERNAL SOURCES: 16 | WAAppRouting: 17 | :path: ../WAAppRouting.podspec 18 | 19 | SPEC CHECKSUMS: 20 | MOOMaskedIconView: 42f22374cd15e81e65a1d67963374a961d94b909 21 | PPHelpMe: 243c40d2fad33ebdcc6b158c0db54893e0cc2d14 22 | PureLayout: f35f5384c9c4e4479df041dbe33ad7577b71ddfb 23 | RZNotificationView: 37b4a32e03a5f44a91ea76465f33313943a874d8 24 | WAAppRouting: f678fa0dd488af81ee04aeab49e577f5ce187ae0 25 | 26 | COCOAPODS: 0.38.2 27 | -------------------------------------------------------------------------------- /SimpleExampleParameters/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - MOOMaskedIconView (0.1.0) 3 | - PPHelpMe (1.0.2) 4 | - PureLayout (3.0.1) 5 | - RZNotificationView (1.1.7): 6 | - MOOMaskedIconView (>= 0.1.0) 7 | - PPHelpMe (>= 1.0.0) 8 | - WAAppRouting (0.0.5) 9 | 10 | DEPENDENCIES: 11 | - PureLayout 12 | - RZNotificationView 13 | - WAAppRouting (from `../WAAppRouting.podspec`) 14 | 15 | EXTERNAL SOURCES: 16 | WAAppRouting: 17 | :path: ../WAAppRouting.podspec 18 | 19 | SPEC CHECKSUMS: 20 | MOOMaskedIconView: 42f22374cd15e81e65a1d67963374a961d94b909 21 | PPHelpMe: 243c40d2fad33ebdcc6b158c0db54893e0cc2d14 22 | PureLayout: f35f5384c9c4e4479df041dbe33ad7577b71ddfb 23 | RZNotificationView: 37b4a32e03a5f44a91ea76465f33313943a874d8 24 | WAAppRouting: f678fa0dd488af81ee04aeab49e577f5ce187ae0 25 | 26 | COCOAPODS: 0.38.2 27 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/WABaseViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseViewController.h" 10 | #import "ArticleAppLinkParameters.h" 11 | 12 | @interface WABaseViewController () 13 | @property (nonatomic, strong) ArticleAppLinkParameters *routingParameters; 14 | @end 15 | 16 | @implementation WABaseViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | self.view.backgroundColor = [UIColor whiteColor]; 21 | } 22 | 23 | + (Class)appLinkParametersClass { 24 | return [ArticleAppLinkParameters class]; 25 | } 26 | 27 | - (void)reloadFromAppLinkRefresh { 28 | 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WABaseViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseViewController.h" 10 | 11 | @implementation WABaseViewController 12 | 13 | - (void)viewDidLoad { 14 | [super viewDidLoad]; 15 | self.view.backgroundColor = [UIColor whiteColor]; 16 | } 17 | 18 | - (void)reloadFromAppLinkRefresh { 19 | 20 | } 21 | 22 | - (void)addSideMenuButton { 23 | self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Left" style:UIBarButtonItemStyleDone target:self action:@selector(pushLeft)]; 24 | } 25 | 26 | - (void)pushLeft { 27 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"pprevealexample://left"]; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Files/WAAppMacros.h: -------------------------------------------------------------------------------- 1 | #ifndef WAAppRouter_WAAppMacros_h 2 | #define WAAppRouter_WAAppMacros_h 3 | 4 | #define WAAppRouterParameterAssert(obj) NSParameterAssert(obj) 5 | #define WAAppRouterClassAssertion(obj, className) WAAppRouterParameterAssert(obj && [obj isKindOfClass:[className class]]) 6 | #define WAAppRouterClassAssertionIfExisting(obj, className) if (obj) { WAAppRouterParameterAssert([obj isKindOfClass:[className class]]); } 7 | 8 | #define WAAppRouterProtocolAssertion(obj, protocolName) WAAppRouterParameterAssert(obj && [obj conformsToProtocol:@protocol(protocolName)]) 9 | #define WAAssert(condition, description) NSAssert(condition, description) 10 | 11 | #ifdef WAAPP_DEBUG 12 | #define WAAppLog(fmt, ...) NSLog((@"WAAppRouting %s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ## __VA_ARGS__); 13 | #else 14 | #define WAAppLog(fmt, ...) 15 | #endif 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /SimpleExample/SimpleExampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | li.wasapp.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | li.wasapp.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | li.wasapp.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /WAAppRoutingTests/WAAppRoutingTestsTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | li.wasapp.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParametersTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | li.wasapp.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Files/UITabBarController+WAAppRoutingContainerPresentationProtocol.m: -------------------------------------------------------------------------------- 1 | // 2 | // UITabBarController+WAAppLinkContainerPresentationProtocol.m 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "UITabBarController+WAAppRoutingContainerPresentationProtocol.h" 10 | #import "WAAppRoutingContainerPresentationProtocol.h" 11 | 12 | @implementation UITabBarController (WAAppRoutingContainerPresentationProtocol) 13 | 14 | - (BOOL)waapplink_selectController:(UIViewController *)controller animated:(BOOL)animated { 15 | // If we cannot find the controller within the tabs, return NO 16 | if (![[self viewControllers] containsObject:controller]) { 17 | return NO; 18 | } 19 | 20 | // Otherwise, select it 21 | [self setSelectedViewController:controller]; 22 | 23 | return YES; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Files/UINavigationController+WAAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // UINavigationController+WAAdditions.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "UINavigationController+WAAdditions.h" 10 | 11 | @implementation UINavigationController (WAAdditions) 12 | 13 | - (UIViewController *)waapp_popToFirstControllerOfClass:(Class)cClass animated:(BOOL)animated { 14 | UIViewController *foundedController = nil; 15 | for (NSInteger i = [self.viewControllers count] - 1 ; i >= 0 ; i--) { 16 | id controller = self.viewControllers[i]; 17 | if ([controller isKindOfClass:cClass]) { 18 | foundedController = controller; 19 | break; 20 | } 21 | } 22 | if (foundedController) { 23 | [self popToViewController:foundedController animated:animated]; 24 | } 25 | 26 | return foundedController; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /PPRevealSample/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - MOOMaskedIconView (0.1.0) 3 | - PPHelpMe (1.0.2) 4 | - PPRevealSideViewController (1.2.2): 5 | - PPHelpMe 6 | - PureLayout (3.0.1) 7 | - RZNotificationView (1.1.7): 8 | - MOOMaskedIconView (>= 0.1.0) 9 | - PPHelpMe (>= 1.0.0) 10 | - WAAppRouting (0.0.5) 11 | 12 | DEPENDENCIES: 13 | - PPRevealSideViewController 14 | - PureLayout 15 | - RZNotificationView 16 | - WAAppRouting (from `../WAAppRouting.podspec`) 17 | 18 | EXTERNAL SOURCES: 19 | WAAppRouting: 20 | :path: ../WAAppRouting.podspec 21 | 22 | SPEC CHECKSUMS: 23 | MOOMaskedIconView: 42f22374cd15e81e65a1d67963374a961d94b909 24 | PPHelpMe: 243c40d2fad33ebdcc6b158c0db54893e0cc2d14 25 | PPRevealSideViewController: be6d88511fcf55ddcfb9e9ad6167644a421e709a 26 | PureLayout: f35f5384c9c4e4479df041dbe33ad7577b71ddfb 27 | RZNotificationView: 37b4a32e03a5f44a91ea76465f33313943a874d8 28 | WAAppRouting: f678fa0dd488af81ee04aeab49e577f5ce187ae0 29 | 30 | COCOAPODS: 0.38.2 31 | -------------------------------------------------------------------------------- /Files/WAAppRouter+WADefaultRouter.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAAppRouter+WADefaultRouter.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 21/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAAppRouter+WADefaultRouter.h" 10 | #import "WAAppRouteMatcher.h" 11 | #import "WAAppRouteRegistrar.h" 12 | #import "WAAppRouteHandler.h" 13 | 14 | @implementation WAAppRouter (WADefaultRouter) 15 | 16 | + (instancetype) defaultRouter { 17 | 18 | // Allocate the default route matcher 19 | WAAppRouteMatcher *routeMatcher = [WAAppRouteMatcher new]; 20 | 21 | // Create the Registrar 22 | WAAppRouteRegistrar *registrar = [WAAppRouteRegistrar registrarWithRouteMatcher:routeMatcher]; 23 | 24 | // Create the route handler 25 | WAAppRouteHandler *routeHandler = [WAAppRouteHandler routeHandlerWithRouteRegistrar:registrar]; 26 | 27 | // Create the router 28 | return [WAAppRouter routerWithRegistrar:registrar 29 | routeHandler:routeHandler]; 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /Files/WAAppRouterMatcherProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAAppRouterMatcherProtocol.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | @protocol WAAppRouteMatcherProtocol 12 | 13 | /** 14 | * This method is used to match a URL against a string pattern 15 | * 16 | * @param url the url you want to match 17 | * @param pathPattern the pattern to match against 18 | * 19 | * @return YES if matches, NO if not 20 | */ 21 | - (BOOL)matchesURL:(NSURL *)url fromPathPattern:(NSString *)pathPattern; 22 | 23 | /** 24 | * Get the route parameters from the URL (like list/3/toto agains list/:itemID/:name would return 3 as itemID and toto as name) 25 | * 26 | * @param url the url you want to grab the parameters from 27 | * @param pathPattern the pattern to match against 28 | * 29 | * @return the parameters 30 | */ 31 | - (NSDictionary *)parametersFromURL:(NSURL *)url withPathPattern:(NSString *)pathPattern; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Files/NSString+WAAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+WAAdditions.m 3 | // PPRevealSample 4 | // 5 | // Created by Marian Paul on 03/09/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "NSString+WAAdditions.h" 10 | 11 | @implementation NSString (WAAdditions) 12 | 13 | - (NSString *)waapp_stringByAddingPercentEscapes { 14 | NSString *result = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes( 15 | kCFAllocatorDefault, 16 | (CFStringRef)self, 17 | NULL, 18 | CFSTR(":/?#[]@!$&’()*+,;="), 19 | kCFStringEncodingUTF8) ); 20 | return result; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /SimpleExample/SimpleExampleTests/SimpleExampleTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SimpleExampleTests.m 3 | // SimpleExampleTests 4 | // 5 | // Created by Marian Paul on 20/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface SimpleExampleTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation SimpleExampleTests 17 | 18 | - (void)setUp { 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 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSampleTests/PPRevealSampleTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // PPRevealSampleTests.m 3 | // PPRevealSampleTests 4 | // 5 | // Created by Marian Paul on 20/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface PPRevealSampleTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation PPRevealSampleTests 17 | 18 | - (void)setUp { 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 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExampleTests/MoreComplexExampleTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // MoreComplexExampleTests.m 3 | // MoreComplexExampleTests 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface MoreComplexExampleTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation MoreComplexExampleTests 17 | 18 | - (void)setUp { 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 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParametersTests/SimpleExampleParametersTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SimpleExampleParametersTests.m 3 | // SimpleExampleParametersTests 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface SimpleExampleParametersTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation SimpleExampleParametersTests 17 | 18 | - (void)setUp { 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 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WABaseDetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseDetailViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseDetailViewController.h" 10 | #import 11 | 12 | @implementation WABaseDetailViewController 13 | 14 | - (void)loadView { 15 | [super loadView]; 16 | 17 | self.label = [UILabel newAutoLayoutView]; 18 | self.label.numberOfLines = 0; 19 | [self.view addSubview:self.label]; 20 | [self.label autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsMake(10.0f, 10.0f, 10.0f, 10.0f)]; 21 | } 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | [self reloadData]; 26 | } 27 | 28 | - (void)reloadData { 29 | if (self.isViewLoaded) { 30 | self.label.text = [NSString stringWithFormat:@"%@\n\nRouteParameters: %@\n\nQueryParameters:%@\nAllParameters: %@", self.appLink.URL, self.appLink.routeParameters, self.appLink.queryParameters, self.appLinkRoutingParameters]; 31 | } 32 | } 33 | 34 | - (void)reloadFromAppLinkRefresh { 35 | [super reloadFromAppLinkRefresh]; 36 | 37 | [self reloadData]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /SimpleExample/SimpleExample/WABaseDetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseDetailViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseDetailViewController.h" 10 | #import 11 | 12 | @implementation WABaseDetailViewController 13 | 14 | - (void)loadView { 15 | [super loadView]; 16 | 17 | self.label = [UILabel newAutoLayoutView]; 18 | self.label.numberOfLines = 0; 19 | [self.view addSubview:self.label]; 20 | [self.label autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsMake(10.0f, 10.0f, 10.0f, 10.0f)]; 21 | } 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | [self reloadData]; 26 | } 27 | 28 | - (void)reloadData { 29 | if (self.isViewLoaded) { 30 | self.label.text = [NSString stringWithFormat:@"%@\n\nRouteParameters: %@\n\nQueryParameters:%@\nAllParameters: %@", self.appLink.URL, self.appLink.routeParameters, self.appLink.queryParameters, self.appLinkRoutingParameters]; 31 | } 32 | } 33 | 34 | - (void)reloadFromAppLinkRefresh { 35 | [super reloadFromAppLinkRefresh]; 36 | 37 | [self reloadData]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WABaseDetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseDetailViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseDetailViewController.h" 10 | #import 11 | 12 | @implementation WABaseDetailViewController 13 | 14 | - (void)loadView { 15 | [super loadView]; 16 | 17 | self.label = [UILabel newAutoLayoutView]; 18 | self.label.numberOfLines = 0; 19 | [self.view addSubview:self.label]; 20 | [self.label autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsMake(10.0f, 10.0f, 10.0f, 10.0f)]; 21 | } 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | [self reloadData]; 26 | } 27 | 28 | - (void)reloadData { 29 | if (self.isViewLoaded) { 30 | self.label.text = [NSString stringWithFormat:@"%@\n\nRouteParameters: %@\n\nQueryParameters:%@\nAllParameters: %@", self.appLink.URL, self.appLink.routeParameters, self.appLink.queryParameters, self.appLinkRoutingParameters]; 31 | } 32 | } 33 | 34 | 35 | - (void)reloadFromAppLinkRefresh { 36 | [super reloadFromAppLinkRefresh]; 37 | 38 | [self reloadData]; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/WABaseDetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseDetailViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseDetailViewController.h" 10 | #import 11 | 12 | @implementation WABaseDetailViewController 13 | 14 | - (void)loadView { 15 | [super loadView]; 16 | 17 | self.label = [UILabel newAutoLayoutView]; 18 | self.label.numberOfLines = 0; 19 | [self.view addSubview:self.label]; 20 | [self.label autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsMake(10.0f, 10.0f, 10.0f, 10.0f)]; 21 | } 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | [self reloadData]; 26 | } 27 | 28 | - (void)reloadData { 29 | if (self.isViewLoaded) { 30 | self.label.text = [NSString stringWithFormat:@"%@\n\nRouteParameters: %@\n\nQueryParameters:%@\nAllParameters: %@", self.appLink.URL, self.appLink.routeParameters, self.appLink.queryParameters, self.appLinkRoutingParameters]; 31 | } 32 | } 33 | 34 | - (void)reloadFromAppLinkRefresh { 35 | [super reloadFromAppLinkRefresh]; 36 | 37 | [self reloadData]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2014, Wasappli 2 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 3 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 4 | The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the Software. 5 | Except as contained in this notice, the name(s) of (the) Author shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from (the )Author. 6 | -------------------------------------------------------------------------------- /Files/WAAppLink.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAAppLink.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAAppLink.h" 10 | #import "WAAppMacros.h" 11 | 12 | #import "NSURL+WAAdditions.h" 13 | 14 | @implementation WAAppLink 15 | 16 | - (instancetype)initWithURL:(NSURL *)url routeParameters:(NSDictionary *)routeParameters { 17 | WAAppRouterClassAssertion(url, NSURL); 18 | WAAppRouterClassAssertionIfExisting(routeParameters, NSDictionary); 19 | 20 | self = [super init]; 21 | 22 | if (self) { 23 | self->_URL = url; 24 | self->_queryParameters = [url waapp_queryParameters]; 25 | self->_routeParameters = routeParameters; 26 | } 27 | 28 | return self; 29 | } 30 | 31 | + (instancetype)appLinkWithURL:(NSURL *)url routeParameters:(NSDictionary *)routeParameters { 32 | return [[self alloc] initWithURL:url routeParameters:routeParameters]; 33 | } 34 | 35 | #pragma mark - Object retrieval from key 36 | 37 | - (id)objectForKeyedSubscript:(NSString *)key { 38 | id value = self.routeParameters[key]; 39 | if (!value) { 40 | value = self.queryParameters[key]; 41 | } 42 | return value; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Files/WAAppRoutingContainerPresentationProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAAppRoutingContainerPresentationProtocol.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | @class WAAppRouteEntity; 12 | 13 | /** 14 | * @brief A protocol used to deal with custom container and presentation 15 | */ 16 | @protocol WAAppRoutingContainerPresentationProtocol 17 | 18 | /** 19 | * Ask the container to select the controller we are trying to display 20 | * 21 | * @param controller the controller we wants to place in stack 22 | * @param animated select it with animation or not 23 | * 24 | * @return YES if shown, NO otherwise 25 | */ 26 | - (BOOL)waapplink_selectController:(UIViewController *)controller animated:(BOOL)animated; 27 | 28 | @optional 29 | 30 | /** 31 | * Ask for the navigation controller to display an entity 32 | * This method is useful when the container allocates the controller on the fly. See 'PPRevealSample' for a more concrete sample 33 | * 34 | * @param entity the entity for which we are looking for a navigation controller 35 | * 36 | * @return a navigation controller 37 | */ 38 | - (UINavigationController *)waapplink_navigationControllerForPresentingEntity:(WAAppRouteEntity *)entity; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Files/WARoutePattern.h: -------------------------------------------------------------------------------- 1 | // 2 | // WARoutePattern.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | /** 12 | @brief A custom implementation of a class which matches the pattern with a string (the url as string) 13 | */ 14 | @interface WARoutePattern : NSObject 15 | 16 | - (instancetype)init NS_UNAVAILABLE; 17 | + (instancetype)new NS_UNAVAILABLE; 18 | 19 | /** 20 | * Init with a pattern like 'list/:itemID/extra' or 'list/_*_/extra' (whithout the '_') 21 | * 22 | * @param pattern the pattern 23 | * 24 | * @return return a fresh pattern matcher 25 | */ 26 | - (instancetype)initWithPattern:(NSString *)pattern NS_DESIGNATED_INITIALIZER; 27 | 28 | /** 29 | * Tests if a route matches the pattern 30 | * 31 | * @param route the route (url as string) 32 | * 33 | * @return YES if matches, NO if not 34 | */ 35 | - (BOOL)matchesRoute:(NSString *)route; 36 | 37 | /** 38 | * Extract parameters from a route giving the original pattern 39 | * Please not that this will not retrieve all parameters under the wildcard if existing 40 | * 41 | * @param route the route (url as string) 42 | * 43 | * @return a dictionary whith the route parameters 44 | */ 45 | - (NSDictionary *)extractParametersFromRoute:(NSString *)route; 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /Files/WAAppRouteHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAAppRouteHandler.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAAppRouteHandlerProtocol.h" 10 | 11 | @class WAAppRouteRegistrar; 12 | 13 | /** 14 | @brief. An implementation of the `WAAppRouteHandlerProtocol` protocol which only deals with navigation controllers and handle a stack 15 | */ 16 | @interface WAAppRouteHandler : NSObject 17 | 18 | - (instancetype)init NS_UNAVAILABLE; 19 | + (instancetype)new NS_UNAVAILABLE; 20 | 21 | /** 22 | * Init with a route registrar. The registrar contains all the `WAAppRouteEntity` and is necessary for retrieving the entity stack. 23 | * 24 | * @param registrar the registrar containing all the entities 25 | * 26 | * @return a route handler to feed the router 27 | */ 28 | - (instancetype)initWithRouteRegistrar:(WAAppRouteRegistrar *)registrar NS_DESIGNATED_INITIALIZER; 29 | 30 | /** 31 | * @see `initWithRouteRegistrar:` 32 | */ 33 | + (instancetype)routeHandlerWithRouteRegistrar:(WAAppRouteRegistrar *)registrar; 34 | 35 | @property (nonatomic, strong, readonly) WAAppRouteRegistrar *registrar; 36 | 37 | @end 38 | 39 | /** 40 | * This key helps to force an animation instead of letting the route handler guess it. Use it on last shot ^^ 41 | */ 42 | FOUNDATION_EXTERN NSString * const kWAAppRoutingForceAnimationKey; -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/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" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /SimpleExample/SimpleExample/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" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /SimpleExample/SimpleExample/WAListDetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1DetailViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAListDetailViewController.h" 10 | #import 11 | 12 | @implementation WAListDetailViewController 13 | 14 | - (instancetype)init { 15 | self = [super init]; 16 | if (self) { 17 | self.title = @"Detail List"; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | UIButton *nextButton = [UIButton newAutoLayoutView]; 26 | [nextButton setTitle:@"Go to extra" forState:UIControlStateNormal]; 27 | [nextButton addTarget:self action:@selector(goNext) forControlEvents:UIControlEventTouchUpInside]; 28 | [nextButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; 29 | [self.view addSubview:nextButton]; 30 | 31 | [nextButton autoAlignAxisToSuperviewAxis:ALAxisVertical]; 32 | [nextButton autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsMake(0.0f, 10.0f, 10.0f, 10.0f) excludingEdge:ALEdgeTop]; 33 | [nextButton autoSetDimension:ALDimensionHeight toSize:40.0f]; 34 | } 35 | 36 | - (void)goNext { 37 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"simpleexample://list/%@/extra", self.appLink.routeParameters[@"itemID"]]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /WAAppRoutingTests/WAAppRoutingTests/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" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/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" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WAList1DetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1DetailViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAList1DetailViewController.h" 10 | #import 11 | 12 | @implementation WAList1DetailViewController 13 | 14 | - (instancetype)init { 15 | self = [super init]; 16 | if (self) { 17 | self.title = @"Detail List 1"; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | UIButton *nextButton = [UIButton newAutoLayoutView]; 26 | [nextButton setTitle:@"Go to extra" forState:UIControlStateNormal]; 27 | [nextButton addTarget:self action:@selector(goNext) forControlEvents:UIControlEventTouchUpInside]; 28 | [nextButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; 29 | [self.view addSubview:nextButton]; 30 | 31 | [nextButton autoAlignAxisToSuperviewAxis:ALAxisVertical]; 32 | [nextButton autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsMake(0.0f, 10.0f, 60.0f, 10.0f) excludingEdge:ALEdgeTop]; 33 | [nextButton autoSetDimension:ALDimensionHeight toSize:40.0f]; 34 | } 35 | 36 | - (void)goNext { 37 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"pprevealexample://list1/%@/extra", @6];//self.appLink.routeParameters[@"itemID"]]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/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" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WAList1DetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1DetailViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAList1DetailViewController.h" 10 | #import 11 | 12 | @implementation WAList1DetailViewController 13 | 14 | - (instancetype)init { 15 | self = [super init]; 16 | if (self) { 17 | self.title = @"Detail List 1"; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | UIButton *nextButton = [UIButton newAutoLayoutView]; 26 | [nextButton setTitle:@"Go to extra" forState:UIControlStateNormal]; 27 | [nextButton addTarget:self action:@selector(goNext) forControlEvents:UIControlEventTouchUpInside]; 28 | [nextButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; 29 | [self.view addSubview:nextButton]; 30 | 31 | [nextButton autoAlignAxisToSuperviewAxis:ALAxisVertical]; 32 | [nextButton autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsMake(0.0f, 10.0f, 60.0f, 10.0f) excludingEdge:ALEdgeTop]; 33 | [nextButton autoSetDimension:ALDimensionHeight toSize:40.0f]; 34 | } 35 | 36 | - (void)goNext { 37 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"morecomplexexample://list1/%@/extra", self.appLink.routeParameters[@"itemID"]]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /WAAppRouting.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "WAAppRouting" 3 | s.version = "0.0.5" 4 | s.summary = "WAAppRouting is a library to help you dealing with routing on your app by controllers. As a key point, it handles a stack of controllers!" 5 | 6 | s.description = <<-DESC 7 | So what is this library useful for? Good question. Let's answer by asking an other question. Have you been struggled at some point by the following issues? : 8 | 9 | - Well, I need to add some shortcuts to some parts of my apps and it seems crappy to manually allocate the path and select the controllers I need. 10 | - I'm tired of using the push view controller method. 11 | - I wish I had some kind of url handling to get to specific parts of my app juste as easily as snapping a finger. 12 | - If it could even handle a controller stack this would juste be awesome. 13 | - I found a library but it's not working with my custom container... 14 | - I found a great library but the route matching is not working with my requirements... 15 | 16 | All this points are answered by `WAAppRouting` (and more) 17 | DESC 18 | 19 | s.homepage = "https://github.com/Wasappli/WAAppRouting" 20 | s.license = { :type => "MIT", :file => "LICENSE" } 21 | s.author = { "Marian Paul" => "marian@wasapp.li" } 22 | s.platform = :ios, "7.0" 23 | s.source = { :git => "https://github.com/Wasappli/WAAppRouting.git", :tag => "0.0.5" } 24 | s.source_files = "Files/*.{h,m}" 25 | s.requires_arc = true 26 | end 27 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/WAListDetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1DetailViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAListDetailViewController.h" 10 | #import 11 | #import "ArticleAppLinkParameters+Additions.h" 12 | 13 | @implementation WAListDetailViewController 14 | 15 | - (instancetype)init { 16 | self = [super init]; 17 | if (self) { 18 | self.title = @"Detail List"; 19 | } 20 | return self; 21 | } 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | 26 | UIButton *nextButton = [UIButton newAutoLayoutView]; 27 | [nextButton setTitle:@"Go to extra" forState:UIControlStateNormal]; 28 | [nextButton addTarget:self action:@selector(goNext) forControlEvents:UIControlEventTouchUpInside]; 29 | [nextButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; 30 | [self.view addSubview:nextButton]; 31 | 32 | [nextButton autoAlignAxisToSuperviewAxis:ALAxisVertical]; 33 | [nextButton autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsMake(0.0f, 10.0f, 10.0f, 10.0f) excludingEdge:ALEdgeTop]; 34 | [nextButton autoSetDimension:ALDimensionHeight toSize:40.0f]; 35 | } 36 | 37 | - (void)goNext { 38 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"simpleexampleparameters://list/%@/extra?%@", [(ArticleAppLinkParameters *)self.appLinkRoutingParameters articleID], [(ArticleAppLinkParameters *)self.appLinkRoutingParameters articleDetailQuery]]; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Files/WAAppLink.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAAppLink.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | /** 12 | * @brief The WAAppLink object acts as the final object you get after opening a URL 13 | * It contains the URL itself, the query parameters and the route parameters if existing. 14 | */ 15 | @interface WAAppLink : NSObject 16 | 17 | - (instancetype)init NS_UNAVAILABLE; 18 | + (instancetype)new NS_UNAVAILABLE; 19 | 20 | /** 21 | * Init with a URL and routes parameters 22 | * 23 | * @param url the url opened 24 | * @param routeParameters the route parameters associated to the url based on the entity path 25 | * 26 | * @return an app link object 27 | */ 28 | - (instancetype)initWithURL:(NSURL *)url routeParameters:(NSDictionary *)routeParameters NS_DESIGNATED_INITIALIZER; 29 | 30 | /** 31 | @see `initWithURL: routeParameters:` 32 | */ 33 | + (instancetype)appLinkWithURL:(NSURL *)url routeParameters:(NSDictionary *)routeParameters; 34 | 35 | /** 36 | * Return the object for the key merged from `queryParameters` and from `routeParameters`. Please not that the `routeParameters` is evaluated first. 37 | * 38 | * @param key the query key of the object you want to retrieve 39 | * 40 | * @return the value for this key 41 | */ 42 | - (id)objectForKeyedSubscript:(NSString *)key; 43 | 44 | @property (nonatomic, copy, readonly) NSURL *URL; 45 | @property (nonatomic, copy, readonly) NSDictionary *queryParameters; 46 | @property (nonatomic, copy, readonly) NSDictionary *routeParameters; 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WAList2ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAList2ViewController.m 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAList2ViewController.h" 10 | 11 | @implementation WAList2ViewController 12 | 13 | static NSString *CellIdentifier = @"CellIdentifier"; 14 | 15 | - (instancetype)init { 16 | self = [super init]; 17 | if (self) { 18 | self.title = @"List 2"; 19 | } 20 | return self; 21 | } 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | [self addSideMenuButton]; 26 | [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier]; 27 | } 28 | 29 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 30 | return 1; 31 | } 32 | 33 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 34 | return 100; 35 | } 36 | 37 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 38 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 39 | cell.textLabel.text = [NSString stringWithFormat:@"Test id %ld", (long)indexPath.row]; 40 | 41 | return cell; 42 | } 43 | 44 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 45 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 46 | 47 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"pprevealexample://list2/%ld?extraParam1=1&extraParam2=toto", (long)indexPath.row]; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WABaseTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseTableViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseTableViewController.h" 10 | #import 11 | 12 | @implementation WABaseTableViewController 13 | 14 | - (void)loadView { 15 | [super loadView]; 16 | 17 | // Allocate table view 18 | UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; 19 | tableView.delegate = self; 20 | tableView.dataSource = self; 21 | tableView.separatorStyle = UITableViewCellSeparatorStyleNone; 22 | 23 | // We are not using UITableViewController because we don't want the view to be the tableview 24 | [self.view addSubview:tableView]; 25 | 26 | // Setup constraints as seen https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/ViewLoadingandUnloading/ViewLoadingandUnloading.html#//apple_ref/doc/uid/TP40007457-CH10-SW36 27 | [tableView autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsZero]; 28 | 29 | self.tableView = tableView; 30 | } 31 | 32 | #pragma mark - UITableView delegate and datasource 33 | 34 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 35 | return 0; 36 | } 37 | 38 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 39 | return 0; 40 | } 41 | 42 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 43 | return nil; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WABaseTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WABaseTableViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WABaseTableViewController.h" 10 | #import 11 | 12 | @implementation WABaseTableViewController 13 | 14 | - (void)loadView { 15 | [super loadView]; 16 | 17 | // Allocate table view 18 | UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; 19 | tableView.delegate = self; 20 | tableView.dataSource = self; 21 | tableView.separatorStyle = UITableViewCellSeparatorStyleNone; 22 | 23 | // We are not using UITableViewController because we don't want the view to be the tableview 24 | [self.view addSubview:tableView]; 25 | 26 | // Setup constraints as seen https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/ViewLoadingandUnloading/ViewLoadingandUnloading.html#//apple_ref/doc/uid/TP40007457-CH10-SW36 27 | [tableView autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsZero]; 28 | 29 | self.tableView = tableView; 30 | } 31 | 32 | #pragma mark - UITableView delegate and datasource 33 | 34 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 35 | return 0; 36 | } 37 | 38 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 39 | return 0; 40 | } 41 | 42 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 43 | return nil; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WAList1ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1ViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAList1ViewController.h" 10 | 11 | @interface WAList1ViewController () 12 | @end 13 | 14 | @implementation WAList1ViewController 15 | 16 | static NSString *CellIdentifier = @"CellIdentifier"; 17 | 18 | - (instancetype)init { 19 | self = [super init]; 20 | if (self) { 21 | self.title = @"List 1"; 22 | } 23 | return self; 24 | } 25 | 26 | - (void)viewDidLoad { 27 | [super viewDidLoad]; 28 | 29 | [self addSideMenuButton]; 30 | 31 | [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier]; 32 | } 33 | 34 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 35 | return 1; 36 | } 37 | 38 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 39 | return 100; 40 | } 41 | 42 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 43 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 44 | cell.textLabel.text = [NSString stringWithFormat:@"Object id %ld", (long)indexPath.row]; 45 | 46 | return cell; 47 | } 48 | 49 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 50 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 51 | 52 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"pprevealexample://list1/%ld", (long)indexPath.row]; 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /WAAppRoutingTests/WAAppRoutingTests/Base.lproj/Main.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 | -------------------------------------------------------------------------------- /WAAppRoutingTests/WAAppRoutingTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | li.wasapp.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WAModalViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAModalViewController.m 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAModalViewController.h" 10 | #import 11 | 12 | @implementation WAModalViewController 13 | 14 | - (instancetype)init { 15 | self = [super init]; 16 | if (self) { 17 | self.title = @"Modal"; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" 26 | style:UIBarButtonItemStyleDone 27 | target:self 28 | action:@selector(dismissController)]; 29 | 30 | UIBarButtonItem *goToButton = [[UIBarButtonItem alloc] initWithTitle:@"Go to list 1 detail" 31 | style:UIBarButtonItemStyleDone 32 | target:self 33 | action:@selector(goToListOneDetail)]; 34 | 35 | self.navigationItem.rightBarButtonItem = goToButton; 36 | self.navigationItem.leftBarButtonItem = cancelButton; 37 | } 38 | 39 | - (void)dismissController { 40 | [self dismissViewControllerAnimated:YES completion:nil]; 41 | } 42 | 43 | - (void)goToListOneDetail { 44 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"pprevealexample://list1/6"]; 45 | [self dismissController]; 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WAModalViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAModalViewController.m 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAModalViewController.h" 10 | #import 11 | 12 | @implementation WAModalViewController 13 | 14 | - (instancetype)init { 15 | self = [super init]; 16 | if (self) { 17 | self.title = @"Modal"; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" 26 | style:UIBarButtonItemStyleDone 27 | target:self 28 | action:@selector(dismissController)]; 29 | 30 | UIBarButtonItem *goToButton = [[UIBarButtonItem alloc] initWithTitle:@"Go to list 1 detail" 31 | style:UIBarButtonItemStyleDone 32 | target:self 33 | action:@selector(goToListOneDetail)]; 34 | 35 | self.navigationItem.rightBarButtonItem = goToButton; 36 | self.navigationItem.leftBarButtonItem = cancelButton; 37 | } 38 | 39 | - (void)dismissController { 40 | [self dismissViewControllerAnimated:YES completion:nil]; 41 | } 42 | 43 | - (void)goToListOneDetail { 44 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"morecomplexexample://list1/6"]; 45 | [self dismissController]; 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /Files/WAAppRouter.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAAppRouter.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | #import "WAAppRouteHandlerProtocol.h" 11 | 12 | @class WAAppRouteRegistrar; 13 | 14 | /** 15 | @brief This class is the input point of the routing. You should ask it to handle a URL 16 | */ 17 | @interface WAAppRouter : NSObject 18 | 19 | - (instancetype)init NS_UNAVAILABLE; 20 | + (instancetype)new NS_UNAVAILABLE; 21 | 22 | /** 23 | * Init the router 24 | * 25 | * @param registrar the registrar which contains all the routes association with entities or blocks 26 | * @param routeHandler the route handler used to deal with controller stack 27 | * 28 | * @return a fresh router 29 | */ 30 | - (instancetype)initWithRegistrar:(WAAppRouteRegistrar *)registrar routeHandler:(id )routeHandler NS_DESIGNATED_INITIALIZER; 31 | 32 | /** 33 | * @see `initWithRegistrar:routeHandler:` 34 | */ 35 | + (instancetype)routerWithRegistrar:(WAAppRouteRegistrar *)registrar routeHandler:(id )routeHandler; 36 | 37 | /** 38 | * Handle the URL you pass it 39 | * 40 | * @param url the url you received from App Delegate 41 | * 42 | * @return YES if the URL is handled, NO otherwise 43 | */ 44 | - (BOOL)handleURL:(NSURL *)url; 45 | 46 | /** 47 | * Handle user activity (iOS 9 feature) 48 | * 49 | * @param userActivity the user activity received on App Delegate 50 | * 51 | * @return YES if the URL is handled, NO otherwise 52 | */ 53 | - (BOOL)handleUserActivity:(NSUserActivity *)userActivity; 54 | 55 | 56 | @property (nonatomic, strong, readonly) WAAppRouteRegistrar *registrar; 57 | @property (nonatomic, strong, readonly) id routeHandler; 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /Files/WAAppRouteHandlerProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAAppRouteHandlerProtocol.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | @class WAAppRouteEntity, WAAppLink; 12 | 13 | /** 14 | * A block to know if an entity should be handled by the block or not 15 | * 16 | * @param routeEntity the entity we wish to show 17 | * 18 | * @return YES if we should continue, NO otherwise 19 | */ 20 | typedef BOOL (^WAAppRouteHandlerShouldHandleAppLinkForRouteEntityBlock)(WAAppRouteEntity *routeEntity); 21 | 22 | /** 23 | * A block used to preconfigured the controller we are trying to place in the stack. This block is called everytime before reloading the controller with the app link 24 | * 25 | * @param controller the controller we will configure 26 | * @param routeEntity the route entity fitting with the controller 27 | * @param appLink the app link which will be set 28 | */ 29 | typedef void (^WAAppRouterTargetControllerPreConfigurationBlock)(UIViewController *controller, WAAppRouteEntity *routeEntity, WAAppLink *appLink); 30 | 31 | @protocol WAAppRouteHandlerProtocol 32 | 33 | /** 34 | * This method is called by the router to handle the controller stack 35 | * 36 | * @param url the url we want to handle 37 | * @param routeEntity the entity which fits the url 38 | * @param appLink the app link the controllers need to get 39 | * 40 | * @return YES if the route has been handled, NO otherwise 41 | */ 42 | - (BOOL)handleURL:(NSURL *)url withRouteEntity:(WAAppRouteEntity *)routeEntity appLink:(WAAppLink *)appLink; 43 | 44 | @optional 45 | 46 | @property (nonatomic, copy) WAAppRouteHandlerShouldHandleAppLinkForRouteEntityBlock shouldHandleAppLinkBlock; 47 | @property (nonatomic, copy) WAAppRouterTargetControllerPreConfigurationBlock controllerPreConfigurationBlock; 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /SimpleExample/SimpleExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | li.wasapp.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | CFBundleURLTypes 45 | 46 | 47 | CFBundleURLName 48 | li.wasapp.simpleexample 49 | CFBundleURLSchemes 50 | 51 | simpleexample 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | li.wasapp.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | CFBundleURLTypes 45 | 46 | 47 | CFBundleURLName 48 | li.wasapp.pprevealexample 49 | CFBundleURLSchemes 50 | 51 | pprevealexample 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | li.wasapp.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | CFBundleURLTypes 45 | 46 | 47 | CFBundleURLName 48 | li.wasapp.morecomplexexample 49 | CFBundleURLSchemes 50 | 51 | morecomplexexample 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | li.wasapp.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | CFBundleURLTypes 45 | 46 | 47 | CFBundleURLName 48 | li.wasapp.simpleexampleparameters 49 | CFBundleURLSchemes 50 | 51 | simpleexampleparameters 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Files/WAAppRouteMatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAAppRouteMatcher.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAAppRouteMatcher.h" 10 | #import "WARoutePattern.h" 11 | 12 | @implementation WAAppRouteMatcher 13 | 14 | - (BOOL)matchesURL:(NSURL *)url fromPathPattern:(NSString *)pathPattern { 15 | BOOL urlMatchesPattern = [self doesPathPattern:pathPattern 16 | matchesRoute:[self pathWithoutScheme:url]]; 17 | 18 | return urlMatchesPattern; 19 | } 20 | 21 | - (NSDictionary *)parametersFromURL:(NSURL *)url withPathPattern:(NSString *)pathPattern { 22 | WARoutePattern *pattern = [[WARoutePattern alloc] initWithPattern:pathPattern]; 23 | NSDictionary *routeParameters = nil; 24 | 25 | routeParameters = [pattern extractParametersFromRoute:[self pathWithoutScheme:url]]; 26 | 27 | return routeParameters; 28 | } 29 | 30 | #pragma mark - Private 31 | 32 | - (BOOL)doesPathPattern:(NSString *)pathPattern matchesRoute:(NSString *)route { 33 | WARoutePattern* pattern = [[WARoutePattern alloc] initWithPattern:pathPattern]; 34 | return [pattern matchesRoute:route]; 35 | } 36 | 37 | - (NSString *)pathWithoutScheme:(NSURL *)url 38 | { 39 | NSString *pathWithoutScheme = nil; 40 | 41 | // Is the scheme is http or https, then do not use the host 42 | // See documentation on Apple side: 43 | // > The scheme of the webpageURL must be http or https. Any other scheme throws an exception. 44 | 45 | if ([url.scheme isEqualToString:@"http"] || [url.scheme isEqualToString:@"https"]) { 46 | pathWithoutScheme = url.path; 47 | // Remove the first slash 48 | pathWithoutScheme = pathWithoutScheme.length > 1 ? [pathWithoutScheme substringFromIndex:1] : pathWithoutScheme; 49 | } 50 | else { 51 | pathWithoutScheme = [url.host stringByAppendingPathComponent:url.path]; 52 | } 53 | 54 | return pathWithoutScheme; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /Files/NSMutableDictionary+WAAppRoutingParameters.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSNSMutableDictionaryDictionary+WAAppRoutingParameters.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 21/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "NSMutableDictionary+WAAppRoutingParameters.h" 10 | #import "NSString+WAAdditions.h" 11 | #import "WAAppMacros.h" 12 | 13 | @implementation NSMutableDictionary (WAAppRoutingParameters) 14 | 15 | - (instancetype)initWithAllowedParameters:(NSArray *)allowedParameters { 16 | 17 | // WARNING NOTICE 18 | // I chose not to deal with allowed parameters on NSDictionary to avoid having a swizzling method 19 | // and mess with everything. Swizzle is evil, evil is swizzle. Repeat after me 20 | return [self init]; 21 | } 22 | 23 | + (instancetype)newWithAllowedParameters:(NSArray *)allowedParameters { 24 | return [[self alloc] initWithAllowedParameters:allowedParameters]; 25 | } 26 | 27 | - (void)mergeWithAppRouterParameters:(id )parameters { 28 | // I do not support yet the merge between objects sharing the same protocol 29 | [self mergeWithRawParameters:(NSDictionary *)parameters]; 30 | } 31 | 32 | - (void)mergeWithRawParameters:(NSDictionary *)rawParameters { 33 | WAAppRouterClassAssertionIfExisting(rawParameters, NSDictionary); 34 | 35 | if (!rawParameters) { 36 | return; 37 | } 38 | 39 | [self setValuesForKeysWithDictionary:rawParameters]; 40 | } 41 | 42 | - (NSString *)queryStringWithWhiteList:(NSArray *)whiteList { 43 | 44 | NSMutableArray* keyValuesPair = [[NSMutableArray alloc] initWithCapacity:[self count]]; 45 | [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { 46 | id value = obj; 47 | if ([value isKindOfClass:[NSString class]]) { 48 | value = [(NSString *)value waapp_stringByAddingPercentEscapes]; 49 | } 50 | [keyValuesPair addObject:[NSString stringWithFormat:@"%@=%@", key, value]]; 51 | }]; 52 | 53 | // Create the query 54 | return [keyValuesPair componentsJoinedByString:@"&"]; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WALeftMenuViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WALeftMenuViewController.m 3 | // PPRevealSample 4 | // 5 | // Created by Marian Paul on 20/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WALeftMenuViewController.h" 10 | 11 | @interface WALeftMenuViewController () 12 | @property (nonatomic, strong) NSArray *array; 13 | @end 14 | 15 | @implementation WALeftMenuViewController 16 | 17 | static NSString *CellIdentifier = @"CellIdentifier"; 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | 22 | self.array = @[ 23 | @"Go to list 1", 24 | @"Go to list 2", 25 | @"Go to list 1 detail" 26 | ]; 27 | 28 | [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier]; 29 | } 30 | 31 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 32 | return 1; 33 | } 34 | 35 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 36 | return [self.array count]; 37 | } 38 | 39 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 40 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 41 | cell.textLabel.text = self.array[indexPath.row]; 42 | 43 | return cell; 44 | } 45 | 46 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 47 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 48 | 49 | switch(indexPath.row) { 50 | case 0: 51 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"pprevealexample://list1"]; 52 | break; 53 | case 1: 54 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"pprevealexample://list2"]; 55 | break; 56 | case 2: 57 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"pprevealexample://list1/3?%@=NO", kWAAppRoutingForceAnimationKey]; 58 | break; 59 | default: 60 | break; 61 | } 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WAList2ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAList2ViewController.m 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAList2ViewController.h" 10 | 11 | @implementation WAList2ViewController 12 | 13 | static NSString *CellIdentifier = @"CellIdentifier"; 14 | 15 | - (instancetype)init { 16 | self = [super init]; 17 | if (self) { 18 | self.title = @"List 2"; 19 | } 20 | return self; 21 | } 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | 26 | [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier]; 27 | 28 | UIBarButtonItem *showModal = [[UIBarButtonItem alloc] initWithTitle:@"Show modal" 29 | style:UIBarButtonItemStyleDone 30 | target:self 31 | action:@selector(showModal)]; 32 | self.navigationItem.rightBarButtonItem = showModal; 33 | } 34 | 35 | - (void) showModal { 36 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"morecomplexexample://modal/"]; 37 | } 38 | 39 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 40 | return 1; 41 | } 42 | 43 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 44 | return 100; 45 | } 46 | 47 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 48 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 49 | cell.textLabel.text = [NSString stringWithFormat:@"Test id %ld", (long)indexPath.row]; 50 | 51 | return cell; 52 | } 53 | 54 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 55 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 56 | 57 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"morecomplexexample://list2/%ld?extraParam1=1&extraParam2=toto", (long)indexPath.row]; 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /WAAppRoutingTests/WAAppRoutingTests/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // WAAppRoutingTests 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // 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. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Files/WAAppRouterParametersProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAAppRouterParametersProtocol.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | @protocol WAAppRouterParametersProtocol 12 | 13 | /** 14 | * Initialize the object with allowed parameters. Pass nil if you want all parameters allowed 15 | * 16 | * @param allowedParameters the allowed parameters which is supposed to be a list of object properties name (and not the url properties name (except for the category on `NSDictionary`)) 17 | * 18 | * @return a fresh object 19 | */ 20 | - (instancetype)initWithAllowedParameters:(NSArray *)allowedParameters; 21 | 22 | /** 23 | * @see `initWithAllowedParameters` 24 | * 25 | * @param allowedParameters the allowed parameters 26 | * 27 | * @return a fresh object 28 | */ 29 | + (instancetype)newWithAllowedParameters:(NSArray *)allowedParameters; 30 | 31 | /** 32 | * Merge with an other object conform to `WAAppRouterParametersProtocol` protocol 33 | * This will not erase nil values 34 | * 35 | * @param parameters the parameters to merge with 36 | */ 37 | - (void)mergeWithAppRouterParameters:(id )parameters; 38 | 39 | /** 40 | * Merge with raw values by using a mapping 41 | * 42 | * @param parameters the parameters from the url itself 43 | */ 44 | - (void)mergeWithRawParameters:(NSDictionary *)parameters; 45 | 46 | /** 47 | * Get a query string from set parameters on the object 48 | * 49 | * @param whiteList the parameters to include which is supposed to be a list of object properties name (and not the url properties name) 50 | * 51 | * @return a string like 'toto=value&titi=value2' 52 | */ 53 | - (NSString *)queryStringWithWhiteList:(NSArray *)whiteList; 54 | 55 | @optional 56 | 57 | /** 58 | * Override this method to return the mapping between the keys (url keys) and values (object properties) 59 | * 60 | * @return a dictionary 61 | */ 62 | - (NSDictionary *)mappingPropertyKey; 63 | 64 | /** 65 | * Return an array with all the properties name you wish not to encode 66 | * 67 | * @return an array with strings matching properties names 68 | */ 69 | - (NSArray *)excludedPropertiesForEncoding; 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WAList1ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1ViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAList1ViewController.h" 10 | 11 | @interface WAList1ViewController () 12 | @end 13 | 14 | @implementation WAList1ViewController 15 | 16 | static NSString *CellIdentifier = @"CellIdentifier"; 17 | 18 | - (instancetype)init { 19 | self = [super init]; 20 | if (self) { 21 | self.title = @"List 1"; 22 | } 23 | return self; 24 | } 25 | 26 | - (void)viewDidLoad { 27 | [super viewDidLoad]; 28 | 29 | UIBarButtonItem *goToList2Modal = [[UIBarButtonItem alloc] initWithTitle:@"Goto list 2 Modal" 30 | style:UIBarButtonItemStyleDone 31 | target:self 32 | action:@selector(gotoList2Modal)]; 33 | self.navigationItem.rightBarButtonItem = goToList2Modal; 34 | 35 | [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier]; 36 | } 37 | 38 | - (void) gotoList2Modal { 39 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"morecomplexexample://list2/%@/modal", self.appLinkRoutingParameters[@"itemID"]]; 40 | } 41 | 42 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 43 | return 1; 44 | } 45 | 46 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 47 | return 100; 48 | } 49 | 50 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 51 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 52 | cell.textLabel.text = [NSString stringWithFormat:@"Object id %ld", (long)indexPath.row]; 53 | 54 | return cell; 55 | } 56 | 57 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 58 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 59 | 60 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"morecomplexexample://list1/%ld?extraParam1=1&extraParam2=toto", (long)indexPath.row]; 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/WAList2DetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAList2DetailViewController.m 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAList2DetailViewController.h" 10 | #import 11 | 12 | @implementation WAList2DetailViewController 13 | 14 | - (instancetype)init { 15 | self = [super init]; 16 | if (self) { 17 | self.title = @"Detail List 2"; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | UIButton *previousButton = [UIButton newAutoLayoutView]; 26 | [previousButton setTitle:@"Go back" forState:UIControlStateNormal]; 27 | [previousButton addTarget:self action:@selector(goBack) forControlEvents:UIControlEventTouchUpInside]; 28 | [previousButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; 29 | [self.view addSubview:previousButton]; 30 | 31 | [previousButton autoAlignAxisToSuperviewAxis:ALAxisVertical]; 32 | [previousButton autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsMake(0.0f, 10.0f, 60.0f, 10.0f) excludingEdge:ALEdgeTop]; 33 | [previousButton autoSetDimension:ALDimensionHeight toSize:40.0f]; 34 | 35 | UIButton *modalButton = [UIButton newAutoLayoutView]; 36 | [modalButton setTitle:@"Modal" forState:UIControlStateNormal]; 37 | [modalButton addTarget:self action:@selector(showModal) forControlEvents:UIControlEventTouchUpInside]; 38 | [modalButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; 39 | [self.view addSubview:modalButton]; 40 | 41 | [modalButton autoAlignAxisToSuperviewAxis:ALAxisVertical]; 42 | [modalButton autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:10.0f]; 43 | [modalButton autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:10.0f]; 44 | [modalButton autoPinEdge:ALEdgeBottom toEdge:ALEdgeTop ofView:previousButton]; 45 | [modalButton autoSetDimension:ALDimensionHeight toSize:40.0f]; 46 | } 47 | 48 | - (void)goBack { 49 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"pprevealexample://list2?%@=YES", kWAAppRoutingForceAnimationKey]; 50 | } 51 | 52 | - (void)showModal { 53 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"pprevealexample://modal"]; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WAList2DetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAList2DetailViewController.m 3 | // MoreComplexExample 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAList2DetailViewController.h" 10 | #import 11 | 12 | @implementation WAList2DetailViewController 13 | 14 | - (instancetype)init { 15 | self = [super init]; 16 | if (self) { 17 | self.title = @"Detail List 2"; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | UIButton *previousButton = [UIButton newAutoLayoutView]; 26 | [previousButton setTitle:@"Go back" forState:UIControlStateNormal]; 27 | [previousButton addTarget:self action:@selector(goBack) forControlEvents:UIControlEventTouchUpInside]; 28 | [previousButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; 29 | [self.view addSubview:previousButton]; 30 | 31 | [previousButton autoAlignAxisToSuperviewAxis:ALAxisVertical]; 32 | [previousButton autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsMake(0.0f, 10.0f, 60.0f, 10.0f) excludingEdge:ALEdgeTop]; 33 | [previousButton autoSetDimension:ALDimensionHeight toSize:40.0f]; 34 | 35 | UIButton *modalButton = [UIButton newAutoLayoutView]; 36 | [modalButton setTitle:@"Modal" forState:UIControlStateNormal]; 37 | [modalButton addTarget:self action:@selector(showModal) forControlEvents:UIControlEventTouchUpInside]; 38 | [modalButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; 39 | [self.view addSubview:modalButton]; 40 | 41 | [modalButton autoAlignAxisToSuperviewAxis:ALAxisVertical]; 42 | [modalButton autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:10.0f]; 43 | [modalButton autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:10.0f]; 44 | [modalButton autoPinEdge:ALEdgeBottom toEdge:ALEdgeTop ofView:previousButton]; 45 | [modalButton autoSetDimension:ALDimensionHeight toSize:40.0f]; 46 | } 47 | 48 | - (void)goBack { 49 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"morecomplexexample://list2/"]; 50 | } 51 | 52 | - (void)showModal { 53 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"morecomplexexample://list2/%@/modal", self.appLinkRoutingParameters[@"itemID"]]; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /SimpleExample/SimpleExample/WAListViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1ViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAListViewController.h" 10 | #import 11 | 12 | @interface WAListViewController () 13 | @end 14 | 15 | @implementation WAListViewController 16 | 17 | static NSString *CellIdentifier = @"CellIdentifier"; 18 | 19 | - (instancetype)init { 20 | self = [super init]; 21 | if (self) { 22 | self.title = @"List"; 23 | } 24 | return self; 25 | } 26 | 27 | - (void)loadView { 28 | [super loadView]; 29 | 30 | // Allocate table view 31 | UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; 32 | tableView.delegate = self; 33 | tableView.dataSource = self; 34 | tableView.separatorStyle = UITableViewCellSeparatorStyleNone; 35 | 36 | // We are not using UITableViewController because we don't want the view to be the tableview 37 | [self.view addSubview:tableView]; 38 | 39 | // Setup constraints as seen https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/ViewLoadingandUnloading/ViewLoadingandUnloading.html#//apple_ref/doc/uid/TP40007457-CH10-SW36 40 | [tableView autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsZero]; 41 | 42 | self.tableView = tableView; 43 | } 44 | 45 | 46 | - (void)viewDidLoad { 47 | [super viewDidLoad]; 48 | 49 | [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier]; 50 | } 51 | 52 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 53 | return 1; 54 | } 55 | 56 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 57 | return 100; 58 | } 59 | 60 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 61 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 62 | cell.textLabel.text = [NSString stringWithFormat:@"Object id %ld", (long)indexPath.row]; 63 | 64 | return cell; 65 | } 66 | 67 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 68 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 69 | 70 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"simpleexample://list/%ld?extraParam1=1&extraParam2=toto", (long)indexPath.row]; 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/WAList1DetailExtraViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1DetailExtraViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAList1DetailExtraViewController.h" 10 | #import 11 | 12 | @implementation WAList1DetailExtraViewController 13 | 14 | - (instancetype)init { 15 | self = [super init]; 16 | if (self) { 17 | self.title = @"Extra List 1"; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | UIButton *subPath1Button = [UIButton newAutoLayoutView]; 26 | [subPath1Button setTitle:@"Go to subpath 1" forState:UIControlStateNormal]; 27 | [subPath1Button addTarget:self action:@selector(goToSubpath1) forControlEvents:UIControlEventTouchUpInside]; 28 | [subPath1Button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; 29 | [self.view addSubview:subPath1Button]; 30 | 31 | UIButton *subPath2Button = [UIButton newAutoLayoutView]; 32 | [subPath2Button setTitle:@"Go to subpath 2" forState:UIControlStateNormal]; 33 | [subPath2Button addTarget:self action:@selector(goToSubpath2) forControlEvents:UIControlEventTouchUpInside]; 34 | [subPath2Button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; 35 | [self.view addSubview:subPath2Button]; 36 | 37 | 38 | [subPath1Button autoAlignAxisToSuperviewAxis:ALAxisVertical]; 39 | [subPath1Button autoPinEdge:ALEdgeLeft toEdge:ALEdgeLeft ofView:subPath2Button]; 40 | [subPath1Button autoPinEdge:ALEdgeRight toEdge:ALEdgeRight ofView:subPath2Button]; 41 | [subPath1Button autoPinEdge:ALEdgeBottom toEdge:ALEdgeTop ofView:subPath2Button withOffset:10.0f]; 42 | [subPath1Button autoSetDimension:ALDimensionHeight toSize:40.0f]; 43 | 44 | [subPath2Button autoAlignAxisToSuperviewAxis:ALAxisVertical]; 45 | [subPath2Button autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsMake(0.0f, 10.0f, 60.0f, 10.0f) excludingEdge:ALEdgeTop]; 46 | [subPath2Button autoSetDimension:ALDimensionHeight toSize:40.0f]; 47 | } 48 | 49 | - (void)goToSubpath1 { 50 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"morecomplexexample://list1/%@/extra/subpath1", self.appLinkRoutingParameters[@"itemID"]]; 51 | } 52 | 53 | - (void)goToSubpath2 { 54 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"morecomplexexample://list1/%@/extra/subpath2", self.appLinkRoutingParameters[@"itemID"]]; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/WAListViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAList1ViewController.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAListViewController.h" 10 | #import 11 | #import "ArticleAppLinkParameters+Additions.h" 12 | 13 | @interface WAListViewController () 14 | @end 15 | 16 | @implementation WAListViewController 17 | 18 | static NSString *CellIdentifier = @"CellIdentifier"; 19 | 20 | - (instancetype)init { 21 | self = [super init]; 22 | if (self) { 23 | self.title = @"List"; 24 | } 25 | return self; 26 | } 27 | 28 | - (void)loadView { 29 | [super loadView]; 30 | 31 | // Allocate table view 32 | UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; 33 | tableView.delegate = self; 34 | tableView.dataSource = self; 35 | tableView.separatorStyle = UITableViewCellSeparatorStyleNone; 36 | 37 | // We are not using UITableViewController because we don't want the view to be the tableview 38 | [self.view addSubview:tableView]; 39 | 40 | // Setup constraints as seen https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/ViewLoadingandUnloading/ViewLoadingandUnloading.html#//apple_ref/doc/uid/TP40007457-CH10-SW36 41 | [tableView autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsZero]; 42 | 43 | self.tableView = tableView; 44 | } 45 | 46 | 47 | - (void)viewDidLoad { 48 | [super viewDidLoad]; 49 | 50 | [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier]; 51 | } 52 | 53 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 54 | return 1; 55 | } 56 | 57 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 58 | return 100; 59 | } 60 | 61 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 62 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 63 | cell.textLabel.text = [NSString stringWithFormat:@"My super article %ld", (long)indexPath.row]; 64 | 65 | return cell; 66 | } 67 | 68 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 69 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 70 | 71 | ArticleAppLinkParameters *params = [(ArticleAppLinkParameters *)self.appLinkRoutingParameters copy]; 72 | params.articleTitle = [NSString stringWithFormat:@"My super article %ld", (long)indexPath.row]; 73 | 74 | [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"simpleexampleparameters://list/%ld?%@", (long)indexPath.row, [params articleDetailQuery]]; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /Files/UIViewController+WAAppLinkParameters.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+WAAppLinkParameters.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 21/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "UIViewController+WAAppLinkParameters.h" 10 | #import "WAAppLink.h" 11 | #import "WAAppMacros.h" 12 | #import "WAAppRouterTargetControllerProtocol.h" 13 | #import "WAAppRouterParametersProtocol.h" 14 | 15 | @import ObjectiveC.runtime; 16 | 17 | @implementation UIViewController (WAAppLinkParameters) 18 | @dynamic appLink; 19 | @dynamic appLinkRoutingParameters; 20 | 21 | - (void)configureWithAppLink:(WAAppLink *)appLink defaultParameters:(id)defaultParameters allowedParameters:(NSArray *)allowedParameters { 22 | 23 | // Check one last time 24 | WAAppRouterProtocolAssertion(self, WAAppRouterTargetControllerProtocol); 25 | 26 | self.appLink = appLink; 27 | 28 | // Grab the parameters from the link 29 | NSMutableDictionary *rawParameters = [NSMutableDictionary dictionaryWithDictionary:appLink.queryParameters]; 30 | if (appLink.routeParameters) { 31 | [rawParameters setValuesForKeysWithDictionary:appLink.routeParameters]; 32 | } 33 | 34 | // Erase all previous params and allocate with allowed parameters provided by the entity 35 | Class parametersClass = Nil; 36 | if ([[self class] respondsToSelector:@selector(appLinkParametersClass)]) { 37 | parametersClass = [[(id)self class] appLinkParametersClass]; 38 | } else { 39 | parametersClass = [NSMutableDictionary class]; 40 | } 41 | 42 | self.appLinkRoutingParameters = [[parametersClass alloc] initWithAllowedParameters:allowedParameters]; 43 | 44 | // Merge with the default parameters provided by the entity 45 | [self.appLinkRoutingParameters mergeWithAppRouterParameters:defaultParameters]; 46 | 47 | // Now set the values from the query itself 48 | [self.appLinkRoutingParameters mergeWithRawParameters:rawParameters]; 49 | 50 | [(id)self reloadFromAppLinkRefresh]; 51 | } 52 | 53 | #pragma mark - Association references 54 | 55 | - (void)setAppLink:(WAAppLink *)appLink { 56 | objc_setAssociatedObject(self, @selector(appLink), appLink, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 57 | } 58 | 59 | - (WAAppLink *)appLink { 60 | return objc_getAssociatedObject(self, @selector(appLink)); 61 | } 62 | 63 | - (void)setAppLinkRoutingParameters:(id)appLinkRoutingParameters { 64 | objc_setAssociatedObject(self, @selector(appLinkRoutingParameters), appLinkRoutingParameters, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 65 | } 66 | 67 | - (id)appLinkRoutingParameters { 68 | return objc_getAssociatedObject(self, @selector(appLinkRoutingParameters)); 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /Files/WAAppRouter.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAAppRouter.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAAppRouter.h" 10 | 11 | #import "WAAppMacros.h" 12 | 13 | #import "WAAppRouteRegistrar.h" 14 | #import "WAAppRouteEntity.h" 15 | #import "WAAppLink.h" 16 | 17 | @interface WAAppRouter () 18 | 19 | @property (nonatomic, strong) WAAppRouteRegistrar *registrar; 20 | @property (nonatomic, strong) id routeHandler; 21 | 22 | @end 23 | 24 | @implementation WAAppRouter 25 | 26 | - (instancetype)initWithRegistrar:(WAAppRouteRegistrar *)registrar routeHandler:(id)routeHandler { 27 | WAAppRouterClassAssertion(registrar, WAAppRouteRegistrar); 28 | WAAppRouterProtocolAssertion(routeHandler, WAAppRouteHandlerProtocol); 29 | 30 | self = [super init]; 31 | if (self) { 32 | self->_registrar = registrar; 33 | self->_routeHandler = routeHandler; 34 | } 35 | 36 | return self; 37 | } 38 | 39 | + (instancetype)routerWithRegistrar:(WAAppRouteRegistrar *)registrar routeHandler:(id)routeHandler { 40 | return [[self alloc] initWithRegistrar:registrar routeHandler:routeHandler]; 41 | } 42 | 43 | - (BOOL)handleURL:(NSURL *)url { 44 | if (!url) { 45 | return NO; 46 | } 47 | 48 | // Check for a block 49 | NSString *blockPathPattern = nil; 50 | WAAppRouteHandlerBlock block = [self.registrar blockHandlerForURL:url pathPattern:&blockPathPattern]; 51 | // Check for an entity 52 | WAAppRouteEntity *routeEntity = [self.registrar entityForURL:url]; 53 | 54 | // If there is nothing then this URL is not handled 55 | if (!routeEntity && !block) { 56 | return NO; 57 | } 58 | 59 | // Get the route parameters 60 | NSDictionary *routeParameters = [self.registrar.routeMatcher parametersFromURL:url 61 | withPathPattern:routeEntity.path ? : blockPathPattern]; 62 | // Init the link 63 | WAAppLink *link = [[WAAppLink alloc] initWithURL:url 64 | routeParameters:routeParameters]; 65 | 66 | // Execute the block if existing 67 | BOOL handled = NO; 68 | if (block) { 69 | handled = YES; 70 | block(link); 71 | } 72 | 73 | if (routeEntity) { 74 | // Handle the entity 75 | handled = [self.routeHandler handleURL:url 76 | withRouteEntity:routeEntity 77 | appLink:link]; 78 | } 79 | 80 | return handled; 81 | } 82 | 83 | - (BOOL)handleUserActivity:(NSUserActivity *)userActivity { 84 | if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) { 85 | return [self handleURL:userActivity.webpageURL]; 86 | } 87 | 88 | return NO; 89 | } 90 | 91 | @end 92 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/PPRevealSideViewController+WAAppRoutingContainerPresentationProtocol.m: -------------------------------------------------------------------------------- 1 | // 2 | // PPRevealSideViewController+WAAppRoutingContainerPresentationProtocol.m 3 | // PPRevealSample 4 | // 5 | // Created by Marian Paul on 20/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "PPRevealSideViewController+WAAppRoutingContainerPresentationProtocol.h" 10 | #import 11 | 12 | @implementation PPRevealSideViewController (WAAppRoutingContainerPresentationProtocol) 13 | 14 | - (BOOL)waapplink_selectController:(UIViewController *)controller animated:(BOOL)animated { 15 | 16 | // Check if the controller we are trying to present is the same class of one preloaded on a side 17 | for (id side in @[@(PPRevealSideDirectionTop), @(PPRevealSideDirectionLeft), @(PPRevealSideDirectionRight), @(PPRevealSideDirectionBottom)]) { 18 | UIViewController *controllerInSide = [self controllerForSide:[side integerValue]]; 19 | if ([[controller class] isEqual:[controllerInSide class]]) { 20 | [self pushViewController:controller 21 | onDirection:[side integerValue] 22 | animated:animated]; 23 | return YES; 24 | } 25 | } 26 | 27 | // Check if the controller we wants to place can fit into the current stack 28 | if ([self.rootViewController isKindOfClass:[UINavigationController class]]) { 29 | 30 | // If the navigation controller of the controller we are trying to place is the same then juste close the PPReveal and let the router handles the stack 31 | if ([controller.navigationController isEqual:self.rootViewController]) { 32 | [self popViewControllerAnimated:animated]; 33 | return YES; 34 | } 35 | else { 36 | // We do not have a navigation controller yet. We need to allocate one and place it into the reveal center with the controller as the root 37 | UINavigationController *navigationController = nil; 38 | if (![controller isKindOfClass:[UINavigationController class]]) { 39 | navigationController = [[UINavigationController alloc] initWithRootViewController:controller]; 40 | } 41 | else { 42 | // This is a weirdo situation which should not event happen 43 | navigationController = (UINavigationController *)controller; 44 | } 45 | 46 | [self popViewControllerWithNewCenterController:navigationController 47 | animated:animated]; 48 | return YES; 49 | } 50 | } 51 | 52 | return NO; 53 | } 54 | 55 | - (UINavigationController *)waapplink_navigationControllerForPresentingEntity:(WAAppRouteEntity *)entity { 56 | 57 | for (id side in @[@(PPRevealSideDirectionTop), @(PPRevealSideDirectionLeft), @(PPRevealSideDirectionRight), @(PPRevealSideDirectionBottom)]) { 58 | UIViewController *controllerInSide = [self controllerForSide:[side integerValue]]; 59 | if ([entity.targetControllerClass isEqual:[controllerInSide class]]) { 60 | return nil; 61 | } 62 | } 63 | 64 | return (UINavigationController *)self.rootViewController; 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /Files/WAAppLinkParameters.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAAppLinkParameters.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | #import "WAAppRouterParametersProtocol.h" 11 | 12 | /** 13 | * @brief This class is the one more thing of this library. @see `WAAppRouterParametersProtocol` 14 | * It's purpose is to simplify the query values you can retrieve after a routing. The job is yours for dealing with it 15 | Let's have a look to an example you can find on `SimpleExampleParameters` sample project. 16 | 17 | First, create a subclass 18 | 19 | ``` 20 | @interface ArticleAppLinkParameters : WAAppLinkParameters 21 | 22 | @property (nonatomic, strong) NSNumber *articleID; 23 | @property (nonatomic, strong) NSString *articleTitle; 24 | @property (nonatomic, strong) NSNumber *displayType; 25 | 26 | @end 27 | ``` 28 | 29 | You can see here three objects which should be mapped to the url keys 30 | You need to override the `mappingKeyProperty` getter 31 | 32 | ``` 33 | - (NSDictionary *)mappingKeyProperty { 34 | return @{ 35 | @"articleID": @"articleID", 36 | @"article_title": @"articleTitle", 37 | @"display_type": @"displayType" 38 | }; 39 | } 40 | ``` 41 | 42 | Next step is to go to your base view controller (if you not yet one it is a good idea to start now) and write some code you can customize. For example, you would deal with values exception here like cannot have a reservation date before today. 43 | 44 | Here is the default implementation idea you can reproduce in your app 45 | 46 | ``` 47 | - (void)configureWithAppLink:(WAAppLink *)appLink defaultParameters:(id)defaultParameters allowedParameters:(NSArray *)allowedParameters { 48 | 49 | // Grab the parameters from the link 50 | NSMutableDictionary *rawParameters = [NSMutableDictionary dictionaryWithDictionary:appLink.queryParameters]; 51 | if (appLink.routeParameters) { 52 | [rawParameters setValuesForKeysWithDictionary:appLink.routeParameters]; 53 | } 54 | 55 | // Erase all previous params and allocate with allowed parameters provided by the entity 56 | self.routingParameters = [[ArticleAppLinkParameters alloc] initWithAllowedParameters:allowedParameters]; 57 | 58 | // Merge with the default parameters provided by the entity 59 | [self.routingParameters mergeWithAppRouterParameters:defaultParameters]; 60 | 61 | // No set the values from the query itself 62 | [self.routingParameters mergeWithRawParameters:rawParameters]; 63 | 64 | // Call reload which is a random method defined for our purpose. This method should be implemented by your subclasses to reload data accordingly 65 | [self reloadFromAppLink]; 66 | } 67 | ``` 68 | 69 | You can now get the value directly 70 | 71 | ``` 72 | self.label.text = [NSString stringWithFormat:@"ArticleID: %@", self.routingParameters.articleID];` 73 | ``` 74 | 75 | You can copy the parameters, set values for a future use 76 | 77 | ``` 78 | ArticleAppLinkParameters *params = [self.routingParameters copy]; 79 | params.articleTitle = [NSString stringWithFormat:@"My super article %ld", (long)indexPath.row]; 80 | ``` 81 | 82 | Grab the query with a white list 83 | 84 | ``` 85 | NSString *query = [params queryStringWithWhiteList:@[@"articleID", @"articleTitle", @"displayType"]; 86 | ``` 87 | */ 88 | @interface WAAppLinkParameters : NSObject 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [V0.0.5](https://github.com/Wasappli/WAAppRouting/releases/tag/0.0.5) 2 | ### Fixes 3 | - Fix route parameters extraction when URL scheme is http(s) by [enfoiro](https://github.com/enfoiro) 4 | - Fixed an issue with query parameters as numbers others than long values 5 | 6 | 7 | ## [V0.0.4](https://github.com/Wasappli/WAAppRouting/releases/tag/0.0.4) 8 | 9 | ### Fixes 10 | - If you provide an entity with a path you already registered using `registerAppRouteEntity:` on `WAAppRouteRegistrar`, then the registrar will ignore that entity. 11 | - Fixed an issue when passing a class on registration which does not exists. The assertion description was wrong. 12 | - Fixed an issue when reusing a navigation controller to place an entity with no previous one. It was simply pushing on stack, expected behavior is to reset the stack and place the controller. 13 | - Fixed an issue with URL and path escaping when you got for example `"name": "Ben & Jerry"`. `&` is now correctly escaped using `CFURLCreateStringByAddingPercentEscapes` 14 | - Fixed an issue when presenting a modal controller over a modal controller. For example for this path: `(...)/redeem{RedeemVC}!/signup{SignupVC}!`. 15 | - Fixed a memory leak on `WAAppLinkParameters` 16 | - Fixing README 17 | - Added some documentation about iOS 9: 18 | - Search (CoreSpotlight) using [WACoreDataSpotlight](https://github.com/Wasappli/WACoreDataSpotlight) which automatically index CoreData 19 | - 3D Touch released with iPhone 6S and iPhone 6+S 20 | 21 | ### Evolutions 22 | - `WAAppLinkParameters` now supports `NSCoding`. This is useful for state preservation and restoration! 23 | - Added an optional method on `WAAppRouterTargetControllerProtocol` to tell the controllers that the next controller has been presented or reloaded. `- (void)waappRoutingDidDisplayController:(UIViewController *)controller withAppLink:(WAAppLink *)appLink;` 24 | 25 | ## [V0.0.3](https://github.com/Wasappli/WAAppRouting/releases/tag/0.0.3) 26 | 27 | ### Fixes 28 | - Fixed an issue with block execution when no entity registered with the same path. 29 | - Check for equality on WAAppRouteEntity before triggering any assertion that the path is already used. 30 | - Fixed the use of `WAAppRouting` in a project linked to an app extension thanks to [@yusefnapora](https://github.com/yusefnapora). @see `WA_APP_EXTENSION` 31 | 32 | ### Evolution 33 | - Added a new way to register your route. Instead of using the `WAAppRouteEntity`, you can now define a path like `@"list{WAListViewController}/:itemID{WAListDetailViewController}/extra{WAListDetailExtraViewController}"`. 34 | 35 | The syntax is the following: 36 | 37 | - `url_path_component{ClassName}` 38 | - `url_path_component1{ClassName1}/url_path_component2{ClassName2}` 39 | - etc 40 | 41 | If you want to present a modal, then simply add `!` after the class you want to present modally like `@"list{WAListViewController}/:itemID{WAListDetailViewController}/modal{WAListDetailExtraViewController}!"` 42 | 43 | 44 | ## [V0.0.2](https://github.com/Wasappli/WAAppRouting/releases/tag/0.0.2) 45 | 46 | * Added support on `NSMutableDictionary` for `WAAppRouterParametersProtocol`. You can now use a mutable dictionary to provide default parameters. 47 | * Simplified behavior on reloading. You now have a category on `UIViewController` which sets the `WAAppLink` and merge parameters. All you need to care about is reloading your interface with new data on `reloadFromAppLinkRefresh` and optionally, return a class for handling the parameters (see 'SimpleExampleParameters') 48 | * Simplified the router allocation 49 | * README update 50 | 51 | -------------------------------------------------------------------------------- /Files/WARoutePattern.m: -------------------------------------------------------------------------------- 1 | // 2 | // WARoutePattern.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 19/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WARoutePattern.h" 10 | #import "WAAppMacros.h" 11 | 12 | @interface WARoutePattern () 13 | 14 | @property (nonatomic, strong) NSString *pattern; 15 | @property (nonatomic, strong) NSArray *patternPathComponents; 16 | @property (nonatomic, assign) BOOL patternHasWildcard; 17 | 18 | @end 19 | 20 | static NSString *WARoutePatternWildcard = @"*"; 21 | static NSString *WARoutePatternObjectPrefix = @":"; 22 | 23 | @implementation WARoutePattern 24 | 25 | - (instancetype)initWithPattern:(NSString *)pattern { 26 | WAAppRouterClassAssertion(pattern, NSString); 27 | 28 | self = [super init]; 29 | if (self) { 30 | self->_pattern = pattern; 31 | self->_patternPathComponents = pattern.pathComponents; 32 | 33 | // Look for wildcard 34 | for (NSString *path in self->_patternPathComponents) { 35 | if ([path isEqualToString:WARoutePatternWildcard]) { 36 | self->_patternHasWildcard = YES; 37 | break; 38 | } 39 | } 40 | } 41 | 42 | return self; 43 | } 44 | 45 | - (BOOL)matchesRoute:(NSString *)route { 46 | NSArray *routePathComponents = route.pathComponents; 47 | 48 | // If the count is not the same and there is no wildcard, no way this can match 49 | // Same if the route has less components than the pattern 50 | if ( 51 | ([routePathComponents count] != [self.patternPathComponents count] && !self.patternHasWildcard) 52 | || 53 | ([routePathComponents count] < [self.patternPathComponents count]) 54 | ) { 55 | return NO; 56 | } 57 | 58 | BOOL matches = YES; 59 | 60 | for (NSInteger i = 0 ; i < [routePathComponents count] ; i++) { 61 | NSString *routePath = routePathComponents[i]; 62 | 63 | // In case the patterns stops before the route 64 | if ([self.patternPathComponents count] <= i) { 65 | if ([[self.patternPathComponents lastObject] isEqualToString:WARoutePatternWildcard]) { 66 | matches = YES; 67 | break; 68 | } 69 | } 70 | 71 | NSString *patternPath = self.patternPathComponents[i]; 72 | 73 | // See if the pattern path is a future object 74 | if ([patternPath hasPrefix:WARoutePatternObjectPrefix]) { 75 | continue; 76 | } 77 | 78 | // If the strings are not equal and the pattern path is not a wildcard, then we are finished 79 | if (![routePath isEqualToString:patternPath] && ![patternPath isEqualToString:WARoutePatternWildcard]) { 80 | matches = NO; 81 | break; 82 | } 83 | } 84 | 85 | return matches; 86 | } 87 | 88 | - (NSDictionary *)extractParametersFromRoute:(NSString *)route { 89 | NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; 90 | 91 | NSArray *routePathComponents = route.pathComponents; 92 | for (NSInteger i = 0 ; i < [routePathComponents count] ; i++) { 93 | if ([self.patternPathComponents count] <= i) { 94 | break; 95 | } 96 | 97 | NSString *patternPath = self.patternPathComponents[i]; 98 | if ([patternPath hasPrefix:WARoutePatternObjectPrefix]) { 99 | NSString *routePath = routePathComponents[i]; 100 | dictionary[[patternPath substringFromIndex:1]] = routePath; 101 | } 102 | } 103 | 104 | return [dictionary copy]; 105 | } 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /SimpleExample/SimpleExample/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /MoreComplexExample/MoreComplexExample/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /WAAppRoutingTests/WAAppRoutingTests/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Files/WAAppRouteEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAAppRouteEntity.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | #import "WAAppRouterParametersProtocol.h" 12 | 13 | /** 14 | * A block called when the entity gets invoked to refresh and get the default parameters. 15 | * 16 | * @return You should return an object conforms to protocol `WAAppRouterParametersProtocol` 17 | */ 18 | typedef id (^WAAppRouterDefaultParametersBuilderBlock)(void); 19 | 20 | /** 21 | @brief 22 | This class is the heart of the router. This is the object you want to create and configure to get the controller stack working automatically or almost. 23 | Please read the README for special considerations. 24 | */ 25 | @interface WAAppRouteEntity : NSObject 26 | 27 | /** 28 | * Initialize your entity with values 29 | * 30 | * @param name This might help in the future (and for now on debug) 31 | * @param path The url path for reaching this entity. Could include the scheme+host (http/https) or the app scheme or not. Please note that only one entity per path is valid. Also supports the joker `*` 32 | * @param sourceControllerClass the controller class shown in the stack before the target controller. Might be nil if modal or if the first one in stack. If nil, then the entity is considered as the first one on the stack 33 | * @param targetControllerClass the target controller class means the controller class you will use to display the path 34 | * @param presentingController the presenting controller to use. Might not be nil except for the modal and will frequently be a `UINavigationController`. Also see special considerations in README for custom container use 35 | * @param prefersModalPresentation set `YES` if you want this to be triggered as a modal 36 | * @param defaultParametersBuilder a block to pass some default parameters 37 | * @param allowedParameters a list of allowed parameters (only works with `WAAppLinkParameters` subclass or any class which implements `WAAppRouterParametersProtocol` where you can control this. Does not work with `NSMutableDictionary` category provided). The values are supposed to be the subclass properties name 38 | * 39 | * @return an entity to feed the router 40 | */ 41 | 42 | - (instancetype)initWithName:(NSString *)name 43 | path:(NSString *)path 44 | sourceControllerClass:(Class)sourceControllerClass 45 | targetControllerClass:(Class)targetControllerClass 46 | presentingController:(UIViewController *)presentingController 47 | prefersModalPresentation:(BOOL)prefersModalPresentation 48 | defaultParametersBuilder:(WAAppRouterDefaultParametersBuilderBlock)defaultParametersBuilder 49 | allowedParameters:(NSArray *)allowedParameters; 50 | 51 | /** 52 | * @see `initWithName:path:sourceControllerClass:targetControllerClass:presentingController:prefersModalPresentation:defaultParametersBuilder:allowedParameters:` 53 | */ 54 | + (instancetype)routeEntityWithName:(NSString *)name 55 | path:(NSString *)path 56 | sourceControllerClass:(Class)sourceControllerClass 57 | targetControllerClass:(Class)targetControllerClass 58 | presentingController:(UIViewController *)presentingController 59 | prefersModalPresentation:(BOOL)prefersModalPresentation 60 | defaultParametersBuilder:(WAAppRouterDefaultParametersBuilderBlock)defaultParametersBuilder 61 | allowedParameters:(NSArray *)allowedParameters; 62 | 63 | @property (nonatomic, strong, readonly) NSString *name; 64 | @property (nonatomic, strong, readonly) NSString *path; 65 | @property (nonatomic, strong, readonly) Class sourceControllerClass; 66 | @property (nonatomic, strong, readonly) Class targetControllerClass; 67 | @property (nonatomic, strong, readonly) UIViewController *presentingController; 68 | @property (nonatomic, assign, readonly) BOOL preferModalPresentation; 69 | @property (nonatomic, strong, readonly) NSArray *allowedParameters; 70 | 71 | @property (nonatomic, copy, readonly ) WAAppRouterDefaultParametersBuilderBlock defaultParametersBuilder; // We are using block to call to refresh parameters if they depend on time or what so ever kind of parameter 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /Files/WAAppRouteRegistrar.h: -------------------------------------------------------------------------------- 1 | // 2 | // WAAppRouteRegistrar.h 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | #import "WAAppRouterMatcherProtocol.h" 11 | #import "WAAppRouteEntity.h" 12 | 13 | @class WAAppLink; 14 | 15 | typedef void (^WAAppRouteHandlerBlock)(WAAppLink *appLink); 16 | 17 | /** 18 | @brief This class intention is to register both `WAAppRouteEntity` objects or blocks matching a path 19 | */ 20 | @interface WAAppRouteRegistrar : NSObject 21 | 22 | - (instancetype)init NS_UNAVAILABLE; 23 | + (instancetype)new NS_UNAVAILABLE; 24 | 25 | /** 26 | * Initialize the registrar with a route matcher 27 | * 28 | * @param routeMatcher the route matcher you wish to use to match urls against patterns 29 | * 30 | * @return a fresh registrar 31 | */ 32 | - (instancetype)initWithRouteMatcher:(id )routeMatcher NS_DESIGNATED_INITIALIZER; 33 | 34 | /** 35 | * @see `initWithRouteMatcher:` 36 | */ 37 | + (instancetype)registrarWithRouteMatcher:(id )routeMatcher; 38 | 39 | /** 40 | * Register a new route entity. Be careful that if you pass the same entity, it won't update the parameters 41 | * 42 | * @param entity the entity to register 43 | */ 44 | - (void)registerAppRouteEntity:(WAAppRouteEntity *)entity; 45 | 46 | /** 47 | * Register a block handler 48 | * 49 | * @param routeBlockHandler the block handler 50 | * @param route the route you want the block to triggers on call 51 | */ 52 | - (void)registerBlockRouteHandler:(WAAppRouteHandlerBlock)routeBlockHandler forRoute:(NSString *)route; 53 | 54 | /** 55 | * @see `registerAppRoutePath:presentingController:defaultParametersBuilderBlock:allowedParametersBlock:` 56 | * 57 | * @param routePath the path with special syntax 58 | * @param presentingController the navigation controller used to display the controllers stack 59 | */ 60 | - (void)registerAppRoutePath:(NSString *)routePath presentingController:(UIViewController *)presentingController; 61 | 62 | /** 63 | * Register a route path. This avoids you to write several route entity. You can then define paths along with their controllers. 64 | * The syntax is the following: 65 | * `url_path_component{ClassName}` 66 | * `url_path_component1{ClassName1}/url_path_component2{ClassName2}` 67 | * 68 | * Optionaly, you can trigger the modal presentation using `!` character. For example: 69 | * `url_path_component{ClassName}/modal{ModalClass}!` 70 | * would result when calling `appscheme://url_path_component/modal` to `ModalClass` instance presented modally after placing `ClassName` in navigation controller stack. 71 | * 72 | * @param routePath the path with special syntax 73 | * @param presentingController the navigation controller used to display the controllers stack 74 | * @param defaultParametersBuilderBlock a block called for each path component found, so that you can provide a block for building default parameters. Yes, this is block inside block 75 | * @param allowedParametersBlock a block called for each path component found, so that you can provide an array of allowed parameters @see `WAAppRouteEntity` 76 | */ 77 | - (void)registerAppRoutePath:(NSString *)routePath presentingController:(UIViewController *)presentingController defaultParametersBuilderBlock:(WAAppRouterDefaultParametersBuilderBlock (^)(NSString *path))defaultParametersBuilderBlock allowedParametersBlock:(NSArray* (^)(NSString *path))allowedParametersBlock; 78 | 79 | /** 80 | * Retrieve an entity from a route URL 81 | * 82 | * @param url the URL you received in input 83 | * 84 | * @return the corresponding entity 85 | */ 86 | - (WAAppRouteEntity *)entityForURL:(NSURL *)url; 87 | 88 | /** 89 | * Get the block handler for a URL 90 | * 91 | * @param url the URL you received in input 92 | * @param pathPattern the pattern used to register the entity 93 | * 94 | * @return the block to execute 95 | */ 96 | - (WAAppRouteHandlerBlock)blockHandlerForURL:(NSURL *)url pathPattern:(NSString *__autoreleasing *)pathPattern; 97 | 98 | /** 99 | * Retrieve an entity from a class you want to display 100 | * 101 | * @param targetClass the class you want to display 102 | * 103 | * @return the corresponding entity 104 | */ 105 | - (WAAppRouteEntity *)entityForTargetClass:(Class)targetClass; 106 | 107 | @property (nonatomic, strong, readonly) id routeMatcher; 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /PPRevealSample/PPRevealSample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // PPRevealSample 4 | // 5 | // Created by Marian Paul on 20/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import 11 | #import 12 | 13 | #import "WAList1ViewController.h" 14 | #import "WALeftMenuViewController.h" 15 | 16 | @interface AppDelegate () 17 | @property (nonatomic, strong) WAAppRouter *router; 18 | @end 19 | 20 | @implementation AppDelegate 21 | 22 | 23 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 24 | 25 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 26 | 27 | // Init the stack 28 | WAList1ViewController *list1 = [[WAList1ViewController alloc] init]; 29 | UINavigationController *list1NavigationController = [[UINavigationController alloc] initWithRootViewController:list1]; 30 | PPRevealSideViewController *revealSideViewController = [[PPRevealSideViewController alloc] initWithRootViewController:list1NavigationController]; 31 | 32 | WALeftMenuViewController *leftMenu = [[WALeftMenuViewController alloc] init]; 33 | [revealSideViewController preloadViewController:leftMenu forSide:PPRevealSideDirectionLeft]; 34 | 35 | // Important things to notice 36 | // When you are dealing with containers which are supposed to allocate the navigation controller on the fly, you should pass the presenting controller as the container and implement the protocol `WAAppRoutingContainerPresentationProtocol` to return a correct navigation controller 37 | 38 | // Init the router 39 | // Create the default router 40 | self.router = [WAAppRouter defaultRouter]; 41 | 42 | // Create the paths 43 | [self.router.registrar registerAppRoutePath:@"list1{WAList1ViewController}/:itemID{WAList1DetailViewController}/extra{WAList1DetailExtraViewController}" presentingController:revealSideViewController]; 44 | [self.router.registrar registerAppRoutePath:@"list2{WAList2ViewController}/:itemID{WAList2DetailViewController}" presentingController:revealSideViewController]; 45 | [self.router.registrar registerAppRoutePath:@"modal{WAModalViewController}!" presentingController:nil]; 46 | [self.router.registrar registerAppRoutePath:@"left{WALeftMenuViewController}" presentingController:revealSideViewController]; 47 | 48 | self.window.rootViewController = revealSideViewController; 49 | 50 | [self.window makeKeyAndVisible]; 51 | 52 | return YES; 53 | } 54 | 55 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)URL sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { 56 | NSLog(@"openURL: %@", URL); 57 | BOOL handleUrl = NO; 58 | 59 | if ([URL.scheme isEqualToString:@"pprevealexample"]) { 60 | handleUrl = [self.router handleURL:URL]; 61 | } 62 | 63 | if (!handleUrl && ([URL.scheme isEqualToString:@"pprevealexample"])) { 64 | NSLog(@"Well, this one is not handled, consider displaying a 404"); 65 | } 66 | 67 | return handleUrl; 68 | } 69 | 70 | - (void)applicationWillResignActive:(UIApplication *)application { 71 | // 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. 72 | // 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. 73 | } 74 | 75 | - (void)applicationDidEnterBackground:(UIApplication *)application { 76 | // 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. 77 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 78 | } 79 | 80 | - (void)applicationWillEnterForeground:(UIApplication *)application { 81 | // 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. 82 | } 83 | 84 | - (void)applicationDidBecomeActive:(UIApplication *)application { 85 | // 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. 86 | } 87 | 88 | - (void)applicationWillTerminate:(UIApplication *)application { 89 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 90 | } 91 | 92 | # pragma Mark - URL Handling 93 | 94 | - (void)goTo:(NSString *)route, ... { 95 | va_list args; 96 | va_start(args, route); 97 | NSString *finalRoute = [[NSString alloc] initWithFormat:route arguments:args]; 98 | va_end(args); 99 | 100 | [self application:(UIApplication *)self openURL:[NSURL URLWithString:finalRoute] sourceApplication:nil annotation:nil]; 101 | } 102 | @end 103 | -------------------------------------------------------------------------------- /Files/WAAppRouteEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // WAAppRouteEntity.m 3 | // WAAppRouter 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "WAAppRouteEntity.h" 10 | #import "WAAppMacros.h" 11 | 12 | #import "WAAppRouterTargetControllerProtocol.h" 13 | 14 | @import ObjectiveC.runtime; 15 | 16 | @implementation WAAppRouteEntity 17 | 18 | - (instancetype)initWithName:(NSString *)name path:(NSString *)path sourceControllerClass:(Class)sourceControllerClass targetControllerClass:(Class)targetControllerClass presentingController:(UIViewController *)presentingController prefersModalPresentation:(BOOL)prefersModalPresentation defaultParametersBuilder:(WAAppRouterDefaultParametersBuilderBlock)defaultParametersBuilder allowedParameters:(NSArray *)allowedParameters { 19 | // Bunch of assertions and check! 20 | WAAppRouterClassAssertion(name, NSString); 21 | WAAppRouterClassAssertion(path, NSString); 22 | WAAppRouterParameterAssert(!sourceControllerClass || (class_isMetaClass(object_getClass(sourceControllerClass)) && [sourceControllerClass conformsToProtocol:@protocol(WAAppRouterTargetControllerProtocol)] && [sourceControllerClass isSubclassOfClass:[UIViewController class]])); 23 | WAAppRouterParameterAssert(!targetControllerClass || class_isMetaClass(object_getClass(targetControllerClass)) && [targetControllerClass conformsToProtocol:@protocol(WAAppRouterTargetControllerProtocol)] && [targetControllerClass isSubclassOfClass:[UIViewController class]]); 24 | WAAppRouterClassAssertionIfExisting(presentingController, UIViewController); 25 | WAAppRouterParameterAssert(!presentingController && prefersModalPresentation || presentingController && !prefersModalPresentation); 26 | WAAppRouterClassAssertionIfExisting(allowedParameters, NSArray); 27 | 28 | self = [super init]; 29 | if (self) { 30 | _name = name; 31 | _path = path; 32 | _sourceControllerClass = sourceControllerClass; 33 | _targetControllerClass = targetControllerClass; 34 | _presentingController = presentingController; 35 | _preferModalPresentation = prefersModalPresentation; 36 | _defaultParametersBuilder = [defaultParametersBuilder copy]; 37 | _allowedParameters = allowedParameters; 38 | } 39 | 40 | return self; 41 | 42 | } 43 | 44 | + (instancetype)routeEntityWithName:(NSString *)name path:(NSString *)path sourceControllerClass:(Class)sourceControllerClass targetControllerClass:(Class)targetControllerClass presentingController:(UIViewController *)presentingController prefersModalPresentation:(BOOL)prefersModalPresentation defaultParametersBuilder:(WAAppRouterDefaultParametersBuilderBlock)defaultParametersBuilder allowedParameters:(NSArray *)allowedParameters { 45 | return [[self alloc] initWithName:name 46 | path:path 47 | sourceControllerClass:sourceControllerClass 48 | targetControllerClass:targetControllerClass 49 | presentingController:presentingController 50 | prefersModalPresentation:prefersModalPresentation 51 | defaultParametersBuilder:defaultParametersBuilder 52 | allowedParameters:allowedParameters]; 53 | } 54 | 55 | - (NSString *)description { 56 | return [NSString stringWithFormat: 57 | @"WAAppRouteEntity description:%@\n" 58 | "name: %@\n" 59 | "path: %@\n" 60 | "sourceControllerClass: %@\n" 61 | "targetControllerClass: %@\n" 62 | "presentingController: %@\n" 63 | "preferModalPresentation: %d\n" 64 | "allowedParameters: %@\n", 65 | [super description], 66 | self.name, 67 | self.path, 68 | NSStringFromClass(self.sourceControllerClass), 69 | NSStringFromClass(self.targetControllerClass), 70 | self.presentingController, 71 | self.preferModalPresentation, 72 | self.allowedParameters]; 73 | } 74 | 75 | #pragma mark - Equality 76 | 77 | - (BOOL)isEqualToRouteEntity:(WAAppRouteEntity *)routeEntity { 78 | if (!routeEntity) { 79 | return NO; 80 | } 81 | 82 | BOOL haveEqualPaths = (!self.path && !routeEntity.path) || [self.path isEqualToString:routeEntity.path]; 83 | BOOL haveEqualSourceClass = (!self.sourceControllerClass && !routeEntity.sourceControllerClass) || [self.sourceControllerClass isEqual:routeEntity.sourceControllerClass]; 84 | BOOL haveEqualTargetClass = (!self.targetControllerClass && !routeEntity.targetControllerClass) || [self.targetControllerClass isEqual:routeEntity.targetControllerClass]; 85 | BOOL haveSamePresentation = (self.preferModalPresentation == routeEntity.preferModalPresentation); 86 | BOOL haveEqualPresentingController = (!self.presentingController && !routeEntity.presentingController) || [self.presentingController isEqual:routeEntity.presentingController]; 87 | 88 | return haveEqualPaths && haveEqualSourceClass && haveEqualTargetClass && haveSamePresentation && haveEqualPresentingController; 89 | } 90 | 91 | #pragma mark NSObject 92 | 93 | - (BOOL)isEqual:(id)object { 94 | if (self == object) { 95 | return YES; 96 | } 97 | 98 | if (![object isKindOfClass:[WAAppRouteEntity class]]) { 99 | return NO; 100 | } 101 | 102 | return [self isEqualToRouteEntity:(WAAppRouteEntity *)object]; 103 | } 104 | 105 | - (NSUInteger)hash { 106 | return [self.path hash] ^ [self.sourceControllerClass hash] ^ [self.targetControllerClass hash] ^ [self.sourceControllerClass hash] + self.preferModalPresentation; 107 | } 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /SimpleExample/SimpleExample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // SimpleDemo 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | #import 12 | #import "WABaseViewController.h" 13 | 14 | #import 15 | 16 | @interface AppDelegate () 17 | @property (nonatomic, strong) WAAppRouter *router; 18 | @end 19 | 20 | @implementation AppDelegate 21 | 22 | // You can open the app using simpleexample://list 23 | 24 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 25 | 26 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 27 | 28 | UINavigationController *navigationController = [[UINavigationController alloc] init]; 29 | 30 | // Create the default router 31 | self.router = [WAAppRouter defaultRouter]; 32 | 33 | // Create the default parameters builder for detail 34 | id (^detailParametersBuilder)(void) = ^id(void) { 35 | NSMutableDictionary *defaultParameters = [NSMutableDictionary new]; 36 | defaultParameters[@"defaultParam"] = @1; 37 | defaultParameters[@"defaultParam2"] = @"Default parameter 2"; 38 | return defaultParameters; 39 | }; 40 | 41 | // Register the path 42 | [self.router.registrar registerAppRoutePath:@"list{WAListViewController}/:itemID{WAListDetailViewController}/extra{WAListDetailExtraViewController}" 43 | presentingController:navigationController 44 | defaultParametersBuilderBlock:^WAAppRouterDefaultParametersBuilderBlock(NSString *path) { 45 | if ([path isEqualToString:@"list/:itemID"]) { 46 | return detailParametersBuilder; 47 | } 48 | return nil; 49 | } 50 | allowedParametersBlock:nil]; 51 | 52 | // Register some blocks 53 | [self.router.registrar registerBlockRouteHandler:^(WAAppLink *appLink) { 54 | [RZNotificationView showNotificationOn:RZNotificationContextAboveStatusBar 55 | message:[NSString stringWithFormat:@"You are dealing with item ID %@", appLink[@"itemID"]] 56 | icon:RZNotificationIconInfo 57 | anchor:RZNotificationAnchorNone 58 | position:RZNotificationPositionTop 59 | color:RZNotificationColorYellow 60 | assetColor:RZNotificationContentColorDark 61 | textColor:RZNotificationContentColorDark 62 | withCompletion:^(BOOL touched) { 63 | 64 | }]; 65 | } 66 | forRoute:@"list/*"]; 67 | 68 | [self.router.routeHandler setShouldHandleAppLinkBlock:^BOOL(WAAppRouteEntity *entity) { 69 | // Could return NO if not logged in for example 70 | return YES; 71 | }]; 72 | 73 | [self.router.routeHandler setControllerPreConfigurationBlock:^(UIViewController *controller, WAAppRouteEntity *routeEntity, WAAppLink *appLink) { 74 | if ([controller isKindOfClass:[WABaseViewController class]]) { 75 | // You could set here some entities like an image cache 76 | ((WABaseViewController *)controller).commonObject = @"Common object from global routing"; 77 | } 78 | }]; 79 | 80 | self.window.rootViewController = navigationController; 81 | 82 | [self.window makeKeyAndVisible]; 83 | 84 | [self goTo:@"simpleexample://list"]; 85 | // [self goTo:@"simpleexample://list/3/extra"]; 86 | 87 | return YES; 88 | } 89 | 90 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)URL sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { 91 | NSLog(@"openURL: %@", URL); 92 | BOOL handleUrl = NO; 93 | 94 | if ([URL.scheme isEqualToString:@"simpleexample"]) { 95 | handleUrl = [self.router handleURL:URL]; 96 | } 97 | 98 | if (!handleUrl && ([URL.scheme isEqualToString:@"simpleexample"])) { 99 | NSLog(@"Well, this one is not handled, consider displaying a 404"); 100 | } 101 | 102 | return handleUrl; 103 | } 104 | 105 | - (void)applicationWillResignActive:(UIApplication *)application { 106 | // 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. 107 | // 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. 108 | } 109 | 110 | - (void)applicationDidEnterBackground:(UIApplication *)application { 111 | // 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. 112 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 113 | } 114 | 115 | - (void)applicationWillEnterForeground:(UIApplication *)application { 116 | // 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. 117 | } 118 | 119 | - (void)applicationDidBecomeActive:(UIApplication *)application { 120 | // 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. 121 | } 122 | 123 | - (void)applicationWillTerminate:(UIApplication *)application { 124 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 125 | } 126 | 127 | # pragma Mark - URL Handling 128 | 129 | - (void)goTo:(NSString *)route, ... { 130 | va_list args; 131 | va_start(args, route); 132 | NSString *finalRoute = [[NSString alloc] initWithFormat:route arguments:args]; 133 | va_end(args); 134 | 135 | [self application:(UIApplication *)self openURL:[NSURL URLWithString:finalRoute] sourceApplication:nil annotation:nil]; 136 | } 137 | 138 | @end 139 | 140 | -------------------------------------------------------------------------------- /SimpleExampleParameters/SimpleExampleParameters/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // SimpleDemo 4 | // 5 | // Created by Marian Paul on 18/08/2015. 6 | // Copyright (c) 2015 Wasappli. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | #import 12 | 13 | #import "WABaseViewController.h" 14 | 15 | #import 16 | 17 | @interface AppDelegate () 18 | @property (nonatomic, strong) WAAppRouter *router; 19 | @end 20 | 21 | @implementation AppDelegate 22 | 23 | // You can open the app using 24 | // simpleexampleparameters://list 25 | 26 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 27 | 28 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 29 | 30 | UINavigationController *navigationController = [[UINavigationController alloc] init]; 31 | 32 | // Create the default router 33 | self.router = [WAAppRouter defaultRouter]; 34 | 35 | // Create the default parameters builder for detail 36 | id (^detailParametersBuilder)(void) = ^id(void) { 37 | ArticleAppLinkParameters *params = [[ArticleAppLinkParameters alloc] initWithAllowedParameters:nil]; 38 | params.displayType = @1; 39 | return params; 40 | }; 41 | 42 | // Register the path 43 | [self.router.registrar registerAppRoutePath:@"list{WAListViewController}/:articleID{WAListDetailViewController}/extra{WAListDetailExtraViewController}" 44 | presentingController:navigationController 45 | defaultParametersBuilderBlock:^WAAppRouterDefaultParametersBuilderBlock(NSString *path) { 46 | if ([path isEqualToString:@"list/:articleID"]) { 47 | return detailParametersBuilder; 48 | } 49 | return nil; 50 | } 51 | allowedParametersBlock:^NSArray *(NSString *path) { 52 | if ([path isEqualToString:@"list/:articleID"]) { 53 | return @[@"articleID", @"articleTitle"]; 54 | } 55 | return nil; 56 | }]; 57 | 58 | // Register some blocks 59 | [self.router.registrar registerBlockRouteHandler:^(WAAppLink *appLink) { 60 | [RZNotificationView showNotificationOn:RZNotificationContextAboveStatusBar 61 | message:[NSString stringWithFormat:@"You are dealing with item ID %@", appLink[@"articleID"]] 62 | icon:RZNotificationIconInfo 63 | anchor:RZNotificationAnchorNone 64 | position:RZNotificationPositionTop 65 | color:RZNotificationColorYellow 66 | assetColor:RZNotificationContentColorDark 67 | textColor:RZNotificationContentColorDark 68 | withCompletion:^(BOOL touched) { 69 | 70 | }]; 71 | } 72 | forRoute:@"list/*"]; 73 | 74 | [self.router.routeHandler setShouldHandleAppLinkBlock:^BOOL(WAAppRouteEntity *entity) { 75 | // Could return NO if not logged in for example 76 | return YES; 77 | }]; 78 | 79 | [self.router.routeHandler setControllerPreConfigurationBlock:^(UIViewController *controller, WAAppRouteEntity *routeEntity, WAAppLink *appLink) { 80 | if ([controller isKindOfClass:[WABaseViewController class]]) { 81 | // You could set here some entities like an image cache 82 | ((WABaseViewController *)controller).commonObject = @"Common object from global routing"; 83 | } 84 | }]; 85 | 86 | self.window.rootViewController = navigationController; 87 | 88 | [self.window makeKeyAndVisible]; 89 | 90 | [self goTo:@"simpleexampleparameters://list"]; 91 | // [self goTo:@"simpleexampleparameters://list/3/extra"]; 92 | 93 | return YES; 94 | } 95 | 96 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)URL sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { 97 | NSLog(@"openURL: %@", URL); 98 | BOOL handleUrl = NO; 99 | 100 | if ([URL.scheme isEqualToString:@"simpleexampleparameters"]) { 101 | handleUrl = [self.router handleURL:URL]; 102 | } 103 | 104 | if (!handleUrl && ([URL.scheme isEqualToString:@"simpleexampleparameters"])) { 105 | NSLog(@"Well, this one is not handled, consider displaying a 404"); 106 | } 107 | 108 | return handleUrl; 109 | } 110 | 111 | - (void)applicationWillResignActive:(UIApplication *)application { 112 | // 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. 113 | // 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. 114 | } 115 | 116 | - (void)applicationDidEnterBackground:(UIApplication *)application { 117 | // 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. 118 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 119 | } 120 | 121 | - (void)applicationWillEnterForeground:(UIApplication *)application { 122 | // 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. 123 | } 124 | 125 | - (void)applicationDidBecomeActive:(UIApplication *)application { 126 | // 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. 127 | } 128 | 129 | - (void)applicationWillTerminate:(UIApplication *)application { 130 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 131 | } 132 | 133 | # pragma Mark - URL Handling 134 | 135 | - (void)goTo:(NSString *)route, ... { 136 | va_list args; 137 | va_start(args, route); 138 | NSString *finalRoute = [[NSString alloc] initWithFormat:route arguments:args]; 139 | va_end(args); 140 | 141 | [self application:(UIApplication *)self openURL:[NSURL URLWithString:finalRoute] sourceApplication:nil annotation:nil]; 142 | } 143 | 144 | @end 145 | 146 | --------------------------------------------------------------------------------