├── .gitignore ├── Example ├── LJRouter.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ ├── LJRouter-Example.xcscheme │ │ └── LJRouterExportModule.xcscheme ├── LJRouter.xcworkspace │ └── contents.xcworkspacedata ├── LJRouter │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── LJAppDelegate.h │ ├── LJAppDelegate.m │ ├── LJHomeComponent │ │ ├── LJHomeTabBarController.m │ │ └── LJHomeViewController.m │ ├── LJLoginComponent │ │ └── LJLoginViewController.m │ ├── LJPersonalComponent │ │ ├── LJMyProfileViewController.m │ │ └── LJSettingViewController.m │ ├── LJRouter-Info.plist │ ├── LJRouter-Prefix.pch │ ├── LJWebviewComponent │ │ └── LJWebViewController.m │ ├── en.lproj │ │ └── InfoPlist.strings │ └── main.m ├── Podfile ├── Podfile.lock ├── Pods │ ├── Headers │ │ ├── Private │ │ │ └── LJRouter │ │ │ │ ├── LJInvocationCenter.h │ │ │ │ ├── LJRouter.h │ │ │ │ ├── LJRouterConvertManager.h │ │ │ │ ├── LJRouterPrivate.h │ │ │ │ ├── LJUrlRouter.h │ │ │ │ ├── UIViewController+LJNavigation.h │ │ │ │ └── metamacros.h │ │ └── Public │ │ │ └── LJRouter │ │ │ ├── LJInvocationCenter.h │ │ │ ├── LJRouter.h │ │ │ ├── LJRouterConvertManager.h │ │ │ ├── LJRouterPrivate.h │ │ │ ├── LJUrlRouter.h │ │ │ ├── UIViewController+LJNavigation.h │ │ │ └── metamacros.h │ ├── Local Podspecs │ │ └── LJRouter.podspec.json │ ├── Manifest.lock │ ├── Pods.xcodeproj │ │ └── project.pbxproj │ └── Target Support Files │ │ ├── LJRouter │ │ ├── LJRouter-dummy.m │ │ ├── LJRouter-prefix.pch │ │ └── LJRouter.xcconfig │ │ └── Pods-LJRouter_Example │ │ ├── Pods-LJRouter_Example-acknowledgements.markdown │ │ ├── Pods-LJRouter_Example-acknowledgements.plist │ │ ├── Pods-LJRouter_Example-dummy.m │ │ ├── Pods-LJRouter_Example-frameworks.sh │ │ ├── Pods-LJRouter_Example-resources.sh │ │ ├── Pods-LJRouter_Example.debug.xcconfig │ │ └── Pods-LJRouter_Example.release.xcconfig └── outputHeaders │ ├── LJHomeComponentHeader.h │ ├── LJLoginComponentHeader.h │ ├── LJPersonalComponentHeader.h │ ├── LJWebviewComponentHeader.h │ ├── action.json │ └── page.json ├── LICENSE ├── LJRouter.podspec ├── LJRouter ├── Core │ ├── LJInvocationCenter.h │ ├── LJInvocationCenter.m │ ├── LJRouter.h │ ├── LJRouter.m │ ├── LJRouterConvertManager.h │ ├── LJRouterConvertManager.m │ ├── LJRouterPrivate.h │ ├── LJUrlRouter.h │ ├── LJUrlRouter.m │ └── metamacros.h ├── ExportDocument │ └── LJRouterExportDevDocument.m ├── ExportTool │ ├── LJRouterExportModule.h │ └── LJRouterExportModule.m └── Navigation │ ├── UIViewController+LJNavigation.h │ └── UIViewController+LJNavigation.m ├── README.md ├── _Pods.xcodeproj └── build /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | # CocoaPods 32 | # 33 | # We recommend against adding the Pods directory to your .gitignore. However 34 | # you should judge for yourself, the pros and cons are mentioned at: 35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 36 | # 37 | # Pods/ 38 | 39 | # Carthage 40 | # 41 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 42 | # Carthage/Checkouts 43 | 44 | Carthage/Build 45 | 46 | # fastlane 47 | # 48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 49 | # screenshots whenever they are needed. 50 | # For more information about the recommended setup visit: 51 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 52 | 53 | fastlane/report.xml 54 | fastlane/Preview.html 55 | fastlane/screenshots 56 | fastlane/test_output 57 | 58 | # Code Injection 59 | # 60 | # After new code Injection tools there's a generated folder /iOSInjectionProject 61 | # https://github.com/johnno1962/injectionforxcode 62 | 63 | iOSInjectionProject/ 64 | -------------------------------------------------------------------------------- /Example/LJRouter.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/LJRouter.xcodeproj/xcshareddata/xcschemes/LJRouter-Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 34 | 40 | 41 | 42 | 43 | 44 | 50 | 51 | 52 | 53 | 54 | 55 | 66 | 68 | 74 | 75 | 76 | 77 | 78 | 79 | 85 | 87 | 93 | 94 | 95 | 96 | 98 | 99 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /Example/LJRouter.xcodeproj/xcshareddata/xcschemes/LJRouterExportModule.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 70 | 71 | 74 | 75 | 76 | 77 | 81 | 82 | 86 | 87 | 91 | 92 | 93 | 94 | 95 | 96 | 102 | 104 | 110 | 111 | 112 | 113 | 115 | 116 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /Example/LJRouter.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/LJRouter/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Example/LJRouter/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Example/LJRouter/LJAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // LJAppDelegate.h 3 | // LJRouter 4 | // 5 | // Created by fover0 on 06/23/2017. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | @import UIKit; 10 | 11 | @interface LJAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Example/LJRouter/LJAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // LJAppDelegate.m 3 | // LJRouter 4 | // 5 | // Created by fover0 on 06/23/2017. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | #import "LJAppDelegate.h" 10 | #import "LJRouter.h" 11 | #import "LJUrlRouter.h" 12 | #import "UIViewController+LJNavigation.h" 13 | 14 | @implementation LJAppDelegate 15 | 16 | LJRouterUsePageObj(webview, (NSString*)url); 17 | - (void)globalConfig 18 | { 19 | [LJRouter sharedInstance].checkPolicy = LJRouterCheckPolicyAssert; 20 | // [LJRouter sharedInstance].checkPolicyModules = @[@"LJPersonalComponent"]; 21 | [LJRouter sharedInstance].createWebviewBlock = ^UIViewController *(NSString *url) { 22 | return get_webview_controller_with_url(url); 23 | }; 24 | 25 | [[LJRouter sharedInstance].convertManager 26 | addConvertJsonValueBlock:^id(LJRouterConvertManager *manager, 27 | void *value, 28 | LJInvocationCenterItemParam *valueParam) { 29 | if ([valueParam.objcClass isKindOfClass:[NSDictionary class]] 30 | || [valueParam.objcClass isKindOfClass:[NSArray class]]) 31 | { 32 | void** p = (void**)value; 33 | id dict = (__bridge id)(*p); 34 | NSData *data = 35 | [NSJSONSerialization dataWithJSONObject:dict 36 | options:0 37 | error:nil]; 38 | return [[NSString alloc] initWithData:data 39 | encoding:NSUTF8StringEncoding]; 40 | } 41 | return nil; 42 | }]; 43 | 44 | [[LJRouter sharedInstance].convertManager addCovertInvokeValueBlock: 45 | ^LJRouterConvertInvokeValue *(LJRouterConvertManager *manager, 46 | id value, 47 | LJInvocationCenterItemParam *targetParam) { 48 | if ([value isKindOfClass:[NSString class]]) 49 | { 50 | if (targetParam.objcClass == [NSDictionary class] 51 | || targetParam.objcClass == [NSArray class]) 52 | { 53 | NSData *stringData = [value dataUsingEncoding:NSUTF8StringEncoding]; 54 | id jsonObj = [NSJSONSerialization JSONObjectWithData:stringData options:0 error:nil]; 55 | if ([jsonObj isKindOfClass:targetParam.objcClass]) 56 | { 57 | return [LJRouterConvertInvokeValue valueWithRetainObj:jsonObj]; 58 | } 59 | } 60 | } 61 | return nil; 62 | }]; 63 | } 64 | 65 | LJRouterUsePageObj(homeTabbar); 66 | 67 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 68 | { 69 | [self globalConfig]; 70 | 71 | UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 72 | UINavigationController *vc = [[UINavigationController alloc] initWithRootViewController:get_homeTabbar_controller()]; 73 | window.rootViewController = vc; 74 | self.window = window ; 75 | [window makeKeyAndVisible]; 76 | 77 | return YES; 78 | } 79 | 80 | - (BOOL)application:(UIApplication *)app 81 | openURL:(NSURL *)url 82 | options:(NSDictionary *)options 83 | { 84 | return 85 | [[LJRouter sharedInstance] routerUrlString:url.absoluteString 86 | sender:self 87 | pageBlock:^(__kindof UIViewController *viewController) { 88 | [UIViewController LJNavigationOpenViewController:viewController]; 89 | } 90 | callbackBlock:nil 91 | canNotRouterBlock:nil]; 92 | } 93 | 94 | - (void)applicationWillResignActive:(UIApplication *)application 95 | { 96 | // 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. 97 | // 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. 98 | } 99 | 100 | - (void)applicationDidEnterBackground:(UIApplication *)application 101 | { 102 | // 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. 103 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 104 | } 105 | 106 | - (void)applicationWillEnterForeground:(UIApplication *)application 107 | { 108 | // 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. 109 | } 110 | 111 | - (void)applicationDidBecomeActive:(UIApplication *)application 112 | { 113 | // 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. 114 | } 115 | 116 | - (void)applicationWillTerminate:(UIApplication *)application 117 | { 118 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 119 | } 120 | 121 | @end 122 | -------------------------------------------------------------------------------- /Example/LJRouter/LJHomeComponent/LJHomeTabBarController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LJHomeTabBarController.m 3 | // invocation 4 | // 5 | // Created by fover0 on 2017/6/20. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | #import "LJRouter.h" 10 | #import "UIViewController+LJNavigation.h" 11 | @interface LJHomeTabBarController : UITabBarController 12 | 13 | @end 14 | 15 | @implementation LJHomeTabBarController 16 | 17 | LJRouterUsePageObj(Home, (NSString*)titlex); 18 | LJRouterUsePageObj(setting); 19 | 20 | @end 21 | 22 | @interface LJHomeTabBarController (something) 23 | 24 | @end 25 | 26 | @implementation LJHomeTabBarController(something) 27 | 28 | LJRouterInit(@"首页tabbar",homeTabbar) 29 | { 30 | self = [self init]; 31 | if (self) 32 | { 33 | NSArray *viewcontrollers = @[ 34 | get_Home_controller_with_titlex(@"我就是个title"), 35 | get_setting_controller(), 36 | ]; 37 | 38 | self.viewControllers = viewcontrollers; 39 | } 40 | return self; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /Example/LJRouter/LJHomeComponent/LJHomeViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LJHomeViewController.m 3 | // invocation 4 | // 5 | // Created by fover0 on 2017/6/8. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | #import "LJRouter.h" 10 | #import "LJUrlRouter.h" 11 | 12 | @interface LJHomeViewController : UIViewController 13 | 14 | @end 15 | 16 | @implementation LJHomeViewController 17 | 18 | LJRouterInit(@"2017年新版首页", 19 | Home, 20 | (NSString*)titlex) 21 | { 22 | self = [super init]; 23 | if (self) 24 | { 25 | self.title = titlex; 26 | } 27 | return self; 28 | } 29 | 30 | - (void)viewDidLoad 31 | { 32 | [super viewDidLoad]; 33 | self.view.backgroundColor = [UIColor whiteColor]; 34 | { 35 | UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100,100,200,100)]; 36 | [btn setTitle:@"push webview with url" forState:0]; 37 | btn.backgroundColor = [UIColor redColor]; 38 | [btn addTarget:self action:@selector(click) forControlEvents:UIControlEventTouchUpInside]; 39 | [self.view addSubview:btn]; 40 | } 41 | { 42 | UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100,300,200,100)]; 43 | [btn setTitle:@"push webview urlstring" forState:0]; 44 | btn.backgroundColor = [UIColor redColor]; 45 | [btn addTarget:self action:@selector(click2) forControlEvents:UIControlEventTouchUpInside]; 46 | [self.view addSubview:btn]; 47 | } 48 | } 49 | 50 | - (void)click 51 | { 52 | [self LJOpenUrlString:@"https://www.lianjia.com"]; 53 | } 54 | 55 | LJRouterUsePage(webview,(NSString*)htmlString); 56 | - (void)click2 57 | { 58 | NSArray *urls = @[@"lianjia://somejscmd?str=heihei&callback=callbackFunction", 59 | @"lianjia://setWebViewTitle?title=你好", 60 | @"lianjia://setWebViewTitle2?title=哈喽", 61 | @"lianjia://myProfile?userId=666", 62 | @"lianjia://myProfile?user={\"userid\":\"123\"}",]; 63 | NSMutableString *string = [[NSMutableString alloc] initWithString:@""]; 64 | 65 | for (NSString *url in urls) 66 | { 67 | [string appendFormat:@"%@

",url,url]; 68 | } 69 | 70 | open_webview_controller_with_htmlString(self, string); 71 | } 72 | 73 | @end 74 | 75 | @interface LJHomeViewController (something) 76 | @end 77 | 78 | @implementation LJHomeViewController (something) 79 | 80 | LJRouterInit(@"泛型测试", objectTypeTest,(NSDictionary*)aaa) 81 | { 82 | return [self init]; 83 | } 84 | 85 | @end 86 | -------------------------------------------------------------------------------- /Example/LJRouter/LJLoginComponent/LJLoginViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LJLoginViewController.m 3 | // invocation 4 | // 5 | // Created by fover0 on 2017/6/20. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | #import "LJRouter.h" 10 | #import "UIViewController+LJNavigation.h" 11 | 12 | @interface LJLoginViewController : UIViewController 13 | @property (nonatomic, copy) void(^finishBlock)(BOOL); 14 | @end 15 | 16 | @implementation LJLoginViewController 17 | 18 | + (void)initialize 19 | { 20 | NSLog(@"%s",__func__); 21 | } 22 | 23 | LJRouterInit(@"登录页面", login) 24 | { 25 | self = [super init]; 26 | if (self) 27 | { 28 | self.ljNavigationType = LJNavigationTypePresentWithNavigation; 29 | self.title = @"登录"; 30 | } 31 | return self; 32 | } 33 | 34 | LJRouterRegistAction(@"判断登录状态,弹出登录页面", loginIfNeed, void, (UIViewController*)curVC, (void(^)(BOOL))finishBlock) 35 | { 36 | if ([[[NSUserDefaults standardUserDefaults] valueForKey:@"islogin"] isEqualToString:@"1"]) 37 | { 38 | if (finishBlock) 39 | { 40 | finishBlock(YES); 41 | } 42 | } 43 | else 44 | { 45 | LJLoginViewController *vc = [self get_login_controller]; 46 | vc.finishBlock = finishBlock; 47 | [curVC LJNavigationOpenViewController:vc]; 48 | } 49 | } 50 | 51 | LJRouterRegistAction(@"是否登录状态", isLogin, BOOL) 52 | { 53 | return [[[NSUserDefaults standardUserDefaults] valueForKey:@"islogin"] isEqualToString:@"1"]; 54 | } 55 | 56 | LJRouterRegistAction(@"退出登录", logout, void) 57 | { 58 | [[NSUserDefaults standardUserDefaults] setValue:nil forKey:@"islogin"]; 59 | } 60 | 61 | 62 | - (void)viewDidLoad 63 | { 64 | [super viewDidLoad]; 65 | self.view.backgroundColor = [UIColor whiteColor]; 66 | { 67 | UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100,100,200,100)]; 68 | [btn setTitle:@"login" forState:0]; 69 | btn.backgroundColor = [UIColor redColor]; 70 | [btn addTarget:self action:@selector(click) forControlEvents:UIControlEventTouchUpInside]; 71 | [self.view addSubview:btn]; 72 | } 73 | 74 | { 75 | UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100,300,200,100)]; 76 | [btn setTitle:@"cancel" forState:0]; 77 | btn.backgroundColor = [UIColor redColor]; 78 | [btn addTarget:self action:@selector(click2) forControlEvents:UIControlEventTouchUpInside]; 79 | [self.view addSubview:btn]; 80 | } 81 | } 82 | 83 | - (void)click 84 | { 85 | [[NSUserDefaults standardUserDefaults] setValue:@"1" forKey:@"islogin"]; 86 | [self closeSelf]; 87 | if (self.finishBlock) 88 | { 89 | self.finishBlock(YES); 90 | } 91 | } 92 | 93 | - (void)click2 94 | { 95 | [self closeSelf]; 96 | if (self.finishBlock) 97 | { 98 | self.finishBlock(NO); 99 | } 100 | 101 | } 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /Example/LJRouter/LJPersonalComponent/LJMyProfileViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LJMyProfileViewController.m 3 | // invocation 4 | // 5 | // Created by fover0 on 2017/6/20. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | #import "LJRouter.h" 10 | #import "UIViewController+LJNavigation.h" 11 | 12 | @interface LJMyProfileViewController : UIViewController 13 | @end 14 | 15 | @implementation LJMyProfileViewController 16 | 17 | LJRouterInit(@"我的个人页",myProfile,(unsigned long)userId) 18 | { 19 | self = [super init]; 20 | if (self) 21 | { 22 | NSString *title = [NSString stringWithFormat:@"我的页面 id=%lu",userId]; 23 | self.title = title; 24 | } 25 | return self; 26 | } 27 | 28 | LJRouterInit(@"个人页", myProfile,(NSDictionary*)user) 29 | { 30 | self = [super init]; 31 | if (self) 32 | { 33 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[[user class] description] 34 | message:user.description 35 | delegate:nil 36 | cancelButtonTitle:@"ok" 37 | otherButtonTitles:nil, nil]; 38 | [alert show]; 39 | } 40 | return self; 41 | } 42 | 43 | - (void)viewDidLoad 44 | { 45 | [super viewDidLoad]; 46 | self.view.backgroundColor = [UIColor whiteColor]; 47 | } 48 | 49 | - (void)viewDidAppear:(BOOL)animated 50 | { 51 | [super viewDidAppear:animated]; 52 | UITabBarController *tabbarController = self.navigationController.viewControllers.firstObject; 53 | [tabbarController.viewControllers enumerateObjectsUsingBlock:^(__kindof UIViewController * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 54 | if ([obj.ljRouterKey isEqualToString:@"setting"]) 55 | { 56 | tabbarController.selectedIndex = idx; 57 | *stop = YES; 58 | return ; 59 | } 60 | }]; 61 | } 62 | 63 | LJRouterUseAction(loginIfNeed, void, (UIViewController*)curVC, (void(^)(BOOL))finishBlock); 64 | - (void)LJNavigationOpenedByViewController:(__kindof UIViewController *)viewController 65 | { 66 | // 这里是登录 67 | action_loginIfNeed_with_curVC_finishBlock(viewController,^(BOOL succeed) { 68 | if (succeed) 69 | { 70 | if ([self.tabBarController.selectedViewController.ljRouterKey isEqualToString:@"setting"]) 71 | { 72 | [super LJNavigationOpenedByViewController:viewController]; 73 | } 74 | else 75 | { 76 | [viewController.navigationController setViewControllers:@[viewController.navigationController.viewControllers.firstObject,self] animated:YES]; 77 | } 78 | } 79 | else 80 | { 81 | // login fail do nothing 82 | } 83 | }); 84 | } 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /Example/LJRouter/LJPersonalComponent/LJSettingViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LJSettingViewController.m 3 | // invocation 4 | // 5 | // Created by fover0 on 2017/6/20. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | #import "LJRouter.h" 10 | 11 | @interface LJSettingViewController : UIViewController 12 | @end 13 | 14 | @implementation LJSettingViewController 15 | 16 | LJRouterInit(@"设置页面", setting) 17 | { 18 | self = [super init]; 19 | if (self) 20 | { 21 | self.title = @"设置"; 22 | } 23 | return self; 24 | } 25 | 26 | - (void)viewDidLoad 27 | { 28 | [super viewDidLoad]; 29 | self.view.backgroundColor = [UIColor whiteColor]; 30 | { 31 | UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100,100,200,100)]; 32 | [btn setTitle:@"个人信息" forState:0]; 33 | btn.backgroundColor = [UIColor redColor]; 34 | [btn addTarget:self action:@selector(click) forControlEvents:UIControlEventTouchUpInside]; 35 | [self.view addSubview:btn]; 36 | } 37 | 38 | { 39 | UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100,300,200,100)]; 40 | [btn setTitle:@"退出登录" forState:0]; 41 | btn.backgroundColor = [UIColor redColor]; 42 | [btn addTarget:self action:@selector(click2) forControlEvents:UIControlEventTouchUpInside]; 43 | [self.view addSubview:btn]; 44 | } 45 | } 46 | 47 | LJRouterUsePage(myProfile, (unsigned long)userId); 48 | - (void)click 49 | { 50 | open_myProfile_controller_with_userId(self, 1000); 51 | } 52 | 53 | LJRouterUseAction(logout, void); 54 | - (void)click2 55 | { 56 | action_logout(); 57 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"已经退出" message:nil preferredStyle:UIAlertControllerStyleAlert]; 58 | [alert addAction:[UIAlertAction actionWithTitle:@"ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 59 | 60 | }]]; 61 | [self presentViewController:alert animated:YES completion:nil]; 62 | } 63 | 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /Example/LJRouter/LJRouter-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleURLTypes 24 | 25 | 26 | CFBundleTypeRole 27 | Editor 28 | CFBundleURLName 29 | lianjia 30 | CFBundleURLSchemes 31 | 32 | lje 33 | 34 | 35 | 36 | CFBundleVersion 37 | 1.0 38 | LSRequiresIPhoneOS 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UISupportedInterfaceOrientations~ipad 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationPortraitUpsideDown 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Example/LJRouter/LJRouter-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifdef __OBJC__ 10 | @import UIKit; 11 | @import Foundation; 12 | #import 13 | #endif 14 | -------------------------------------------------------------------------------- /Example/LJRouter/LJWebviewComponent/LJWebViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LJWebViewController.m 3 | // invocation 4 | // 5 | // Created by fover0 on 2017/6/18. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | #import "LJRouter.h" 10 | #import "LJUrlRouter.h" 11 | 12 | @interface LJWebViewController : UIViewController 13 | @property (nonatomic, retain) UIWebView *webview; 14 | @property (nonatomic, copy) NSString *htmlString; 15 | @property (nonatomic, copy) NSString *url; 16 | @end 17 | 18 | @implementation LJWebViewController 19 | 20 | LJRouterInit(@"webview", 21 | webview, 22 | (NSString*)url) 23 | { 24 | self = [super initWithNibName:nil bundle:nil]; 25 | if (self) 26 | { 27 | self.url = url; 28 | } 29 | return self; 30 | } 31 | 32 | LJRouterInit(@"webview", 33 | webview, 34 | (NSString*)htmlString) 35 | { 36 | self = [super initWithNibName:nil bundle:nil]; 37 | if (self) 38 | { 39 | self.htmlString = htmlString; 40 | } 41 | return self; 42 | } 43 | 44 | 45 | LJRouterRegistAction(@"接收js命令// 接收一个字符串 添加_haha结尾", 46 | somejscmd, 47 | void,(NSString*)str, 48 | (LJRouterCallbackBlock)callback) 49 | { 50 | callback(@"1",NO); 51 | callback(@"2",NO); 52 | callback([str stringByAppendingString:@"_haha"],YES); 53 | } 54 | 55 | LJRouterRegistAction(@"设置UIWebView标题", setWebViewTitle, void,(UIWebView*)sender,(NSString*)title) 56 | { 57 | if (![sender isKindOfClass:[UIView class]]) 58 | { 59 | return; 60 | } 61 | UIResponder *responder = sender ; 62 | while (responder) { 63 | responder = [responder nextResponder]; 64 | if ([responder isKindOfClass:[UIViewController class]]) 65 | { 66 | UIViewController *vc = (id)responder; 67 | vc.title = title; 68 | } 69 | } 70 | } 71 | 72 | LJRouterRegistAction(@"设置UIWebView标题", setWebViewTitle2, void,(LJRouterSenderContext*)sender,(NSString*)title) 73 | { 74 | sender.contextViewController.title = title; 75 | } 76 | 77 | - (void)viewDidLoad { 78 | [super viewDidLoad]; 79 | UIWebView *webview = [[UIWebView alloc] initWithFrame:self.view.bounds]; 80 | self.webview = webview; 81 | [self.view addSubview:webview]; 82 | webview.delegate = self; 83 | 84 | 85 | if (self.url.length) 86 | { 87 | [webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.url]]]; 88 | } 89 | else if (self.htmlString.length) 90 | { 91 | [webview loadHTMLString:self.htmlString baseURL:nil]; 92 | } 93 | } 94 | 95 | - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 96 | { 97 | if ([request.URL.scheme hasPrefix:@"lianjia"]) 98 | { 99 | return ! 100 | [[LJRouter sharedInstance] routerUrlString:request.URL.absoluteString 101 | sender:webView 102 | pageBlock:^(__kindof UIViewController *viewController) { 103 | [[LJRouter sharedInstance] openViewController:viewController withSender:self]; 104 | } 105 | callbackBlock:^(NSString *key, NSString *value, NSString *data, BOOL complete) { 106 | if (value.length && data.length) 107 | { 108 | NSString *cmd = [[NSString alloc] initWithFormat:@"%@('%@');",value,data]; 109 | [self.webview stringByEvaluatingJavaScriptFromString:cmd]; 110 | } 111 | } 112 | canNotRouterBlock:nil]; 113 | } 114 | return YES; 115 | } 116 | 117 | @end 118 | -------------------------------------------------------------------------------- /Example/LJRouter/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/LJRouter/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // LJRouter 4 | // 5 | // Created by fover0 on 06/23/2017. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | @import UIKit; 10 | #import "LJAppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) 13 | { 14 | @autoreleasepool { 15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([LJAppDelegate class])); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | source 'http://git.lianjia.com/mobile_ios/Lianjia_component_Podspec.git' 2 | 3 | target 'LJRouter_Example' do 4 | pod 'LJRouter', :path => '../' 5 | end 6 | 7 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - LJRouter (0.7.0): 3 | - LJRouter/Core (= 0.7.0) 4 | - LJRouter/Navigation (= 0.7.0) 5 | - LJRouter/Core (0.7.0) 6 | - LJRouter/Navigation (0.7.0) 7 | 8 | DEPENDENCIES: 9 | - LJRouter (from `../`) 10 | 11 | EXTERNAL SOURCES: 12 | LJRouter: 13 | :path: ../ 14 | 15 | SPEC CHECKSUMS: 16 | LJRouter: d053c8cc9b7f54bf18a2a3dca9ddf61ace7ec00c 17 | 18 | PODFILE CHECKSUM: 31444511aaf50633ab2e4b8ab8d4887ee12ec0e6 19 | 20 | COCOAPODS: 1.4.0.rc.1 21 | -------------------------------------------------------------------------------- /Example/Pods/Headers/Private/LJRouter/LJInvocationCenter.h: -------------------------------------------------------------------------------- 1 | ../../../../../LJRouter/Core/LJInvocationCenter.h -------------------------------------------------------------------------------- /Example/Pods/Headers/Private/LJRouter/LJRouter.h: -------------------------------------------------------------------------------- 1 | ../../../../../LJRouter/Core/LJRouter.h -------------------------------------------------------------------------------- /Example/Pods/Headers/Private/LJRouter/LJRouterConvertManager.h: -------------------------------------------------------------------------------- 1 | ../../../../../LJRouter/Core/LJRouterConvertManager.h -------------------------------------------------------------------------------- /Example/Pods/Headers/Private/LJRouter/LJRouterPrivate.h: -------------------------------------------------------------------------------- 1 | ../../../../../LJRouter/Core/LJRouterPrivate.h -------------------------------------------------------------------------------- /Example/Pods/Headers/Private/LJRouter/LJUrlRouter.h: -------------------------------------------------------------------------------- 1 | ../../../../../LJRouter/Core/LJUrlRouter.h -------------------------------------------------------------------------------- /Example/Pods/Headers/Private/LJRouter/UIViewController+LJNavigation.h: -------------------------------------------------------------------------------- 1 | ../../../../../LJRouter/Navigation/UIViewController+LJNavigation.h -------------------------------------------------------------------------------- /Example/Pods/Headers/Private/LJRouter/metamacros.h: -------------------------------------------------------------------------------- 1 | ../../../../../LJRouter/Core/metamacros.h -------------------------------------------------------------------------------- /Example/Pods/Headers/Public/LJRouter/LJInvocationCenter.h: -------------------------------------------------------------------------------- 1 | ../../../../../LJRouter/Core/LJInvocationCenter.h -------------------------------------------------------------------------------- /Example/Pods/Headers/Public/LJRouter/LJRouter.h: -------------------------------------------------------------------------------- 1 | ../../../../../LJRouter/Core/LJRouter.h -------------------------------------------------------------------------------- /Example/Pods/Headers/Public/LJRouter/LJRouterConvertManager.h: -------------------------------------------------------------------------------- 1 | ../../../../../LJRouter/Core/LJRouterConvertManager.h -------------------------------------------------------------------------------- /Example/Pods/Headers/Public/LJRouter/LJRouterPrivate.h: -------------------------------------------------------------------------------- 1 | ../../../../../LJRouter/Core/LJRouterPrivate.h -------------------------------------------------------------------------------- /Example/Pods/Headers/Public/LJRouter/LJUrlRouter.h: -------------------------------------------------------------------------------- 1 | ../../../../../LJRouter/Core/LJUrlRouter.h -------------------------------------------------------------------------------- /Example/Pods/Headers/Public/LJRouter/UIViewController+LJNavigation.h: -------------------------------------------------------------------------------- 1 | ../../../../../LJRouter/Navigation/UIViewController+LJNavigation.h -------------------------------------------------------------------------------- /Example/Pods/Headers/Public/LJRouter/metamacros.h: -------------------------------------------------------------------------------- 1 | ../../../../../LJRouter/Core/metamacros.h -------------------------------------------------------------------------------- /Example/Pods/Local Podspecs/LJRouter.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "LJRouter", 3 | "version": "0.7.0", 4 | "summary": "链家iOS路由方案", 5 | "description": "LJRouter是链家独立开发完成的ios客户端路由跳转模块,该模块在接入,安全性,易用性都有比较好的表现,一行代码即可支持h5交互,push跳转,url scheme跳转等功能并实时生成文档.", 6 | "homepage": "https://github.com/LianjiaTech/LJRouter", 7 | "license": { 8 | "type": "MIT", 9 | "file": "LICENSE" 10 | }, 11 | "authors": { 12 | "chenxi": "fover0@126.com" 13 | }, 14 | "source": { 15 | "git": "https://github.com/LianjiaTech/LJRouter.git", 16 | "tag": "0.7.0" 17 | }, 18 | "preserve_paths": [ 19 | "LJRouter/ExportTool", 20 | "LJRouter/ExportDocument", 21 | "build" 22 | ], 23 | "platforms": { 24 | "ios": "8.0" 25 | }, 26 | "ios": { 27 | "frameworks": "UIKit" 28 | }, 29 | "default_subspecs": [ 30 | "Core", 31 | "Navigation" 32 | ], 33 | "subspecs": [ 34 | { 35 | "name": "Core", 36 | "source_files": "LJRouter/Core/**/*" 37 | }, 38 | { 39 | "name": "Navigation", 40 | "source_files": "LJRouter/Navigation/**/*" 41 | } 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /Example/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - LJRouter (0.7.0): 3 | - LJRouter/Core (= 0.7.0) 4 | - LJRouter/Navigation (= 0.7.0) 5 | - LJRouter/Core (0.7.0) 6 | - LJRouter/Navigation (0.7.0) 7 | 8 | DEPENDENCIES: 9 | - LJRouter (from `../`) 10 | 11 | EXTERNAL SOURCES: 12 | LJRouter: 13 | :path: ../ 14 | 15 | SPEC CHECKSUMS: 16 | LJRouter: d053c8cc9b7f54bf18a2a3dca9ddf61ace7ec00c 17 | 18 | PODFILE CHECKSUM: 31444511aaf50633ab2e4b8ab8d4887ee12ec0e6 19 | 20 | COCOAPODS: 1.4.0.rc.1 21 | -------------------------------------------------------------------------------- /Example/Pods/Pods.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0083AD54101A8F2BC28D49D9EB763D0B /* LJUrlRouter.h in Headers */ = {isa = PBXBuildFile; fileRef = 92BD04E298C527A993D751A7C4E1A4DB /* LJUrlRouter.h */; settings = {ATTRIBUTES = (Project, ); }; }; 11 | 1035915AE1C08B61DC1E9EF0E95B1FF8 /* Pods-LJRouter_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = C424084C8EE1138C637D11025DC793B1 /* Pods-LJRouter_Example-dummy.m */; }; 12 | 23570B18BE6B1B9FFC424F8810669353 /* LJRouterPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5055C7A26BFE8346EB06FC9AE2B30A84 /* LJRouterPrivate.h */; settings = {ATTRIBUTES = (Project, ); }; }; 13 | 48BF8C7DE9DBE5A20CD338741D476CBA /* LJRouter.h in Headers */ = {isa = PBXBuildFile; fileRef = 5253CBE066A29BEC2D8ED51A7688C504 /* LJRouter.h */; settings = {ATTRIBUTES = (Project, ); }; }; 14 | 665FB8709EB20255F270B3BB34D88B82 /* metamacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 0DC2F486D6A8BCD8F34CE19A2DC87D43 /* metamacros.h */; settings = {ATTRIBUTES = (Project, ); }; }; 15 | 6731DAC759CA8658E123FB13446E536F /* LJRouter-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = CB871749505B51AFD97BFC6EB727B6C4 /* LJRouter-dummy.m */; }; 16 | 68518674328950BAF3BEC991415DEAD9 /* LJUrlRouter.m in Sources */ = {isa = PBXBuildFile; fileRef = 869699ECA91E76BDFFD3653A042ECC7B /* LJUrlRouter.m */; }; 17 | 6D0B910509F817D70D790C8B3805AF36 /* LJRouter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C26D5A481D864D7D66AE596AF516E34 /* LJRouter.m */; }; 18 | 729D3AFB73234094614EE8A20C565055 /* LJRouterConvertManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 3022823B2E59F6312D3679DEC79D2812 /* LJRouterConvertManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; 19 | 7A40A411BDDC481FE089F9032DA92BCB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D88AAE1F92055A60CC2FC970D7D34634 /* Foundation.framework */; }; 20 | 81440BE60992DE7F04E32F4D384C221C /* UIViewController+LJNavigation.h in Headers */ = {isa = PBXBuildFile; fileRef = 9384EA1EC3F9F880AA95D9CAAB2448D8 /* UIViewController+LJNavigation.h */; settings = {ATTRIBUTES = (Project, ); }; }; 21 | 834C0829F0FE1DB8C77F46B8D06ABC05 /* LJRouterConvertManager.m in Sources */ = {isa = PBXBuildFile; fileRef = CE3F4E9A34CAE905CF1E57C8C16D397F /* LJRouterConvertManager.m */; }; 22 | 8B0146414ECA1EA9F23A87BCEBDAA59D /* UIViewController+LJNavigation.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F713603D0BC5DAC1825045E3C343A24 /* UIViewController+LJNavigation.m */; }; 23 | C15B89E3AF780159CA74790D99D19DAE /* LJInvocationCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = CDE6E56A0E64223D07310757724CC6AC /* LJInvocationCenter.m */; }; 24 | C97CB8CFFDBAEAA0E9367845FAD5094B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D88AAE1F92055A60CC2FC970D7D34634 /* Foundation.framework */; }; 25 | E0BE10049AAC2890F685169DBA6ED71F /* LJInvocationCenter.h in Headers */ = {isa = PBXBuildFile; fileRef = 18D79562941659CE24837C803B462E99 /* LJInvocationCenter.h */; settings = {ATTRIBUTES = (Project, ); }; }; 26 | F9546ED236764DFF2BDFF8BF59EC01A2 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B63C6A64CF66340668996F78DA6BB482 /* UIKit.framework */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXContainerItemProxy section */ 30 | B7187F05F56362033182C1726625EA75 /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = AEE6E99EB3157BC0AFF77C9FE07B7392; 35 | remoteInfo = LJRouter; 36 | }; 37 | /* End PBXContainerItemProxy section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | 0DC2F486D6A8BCD8F34CE19A2DC87D43 /* metamacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = metamacros.h; path = LJRouter/Core/metamacros.h; sourceTree = ""; }; 41 | 0FB445BF0199E908BD39EB33182BF612 /* libPods-LJRouter_Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "libPods-LJRouter_Example.a"; path = "libPods-LJRouter_Example.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | 18D79562941659CE24837C803B462E99 /* LJInvocationCenter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LJInvocationCenter.h; path = LJRouter/Core/LJInvocationCenter.h; sourceTree = ""; }; 43 | 193344E2033F65E4E73190FB2BF8DCBF /* libLJRouter.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = libLJRouter.a; path = libLJRouter.a; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 2114385887C3BC99E5382E89DB279F5F /* LJRouter.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; path = LJRouter.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 45 | 2F713603D0BC5DAC1825045E3C343A24 /* UIViewController+LJNavigation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIViewController+LJNavigation.m"; path = "LJRouter/Navigation/UIViewController+LJNavigation.m"; sourceTree = ""; }; 46 | 3022823B2E59F6312D3679DEC79D2812 /* LJRouterConvertManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LJRouterConvertManager.h; path = LJRouter/Core/LJRouterConvertManager.h; sourceTree = ""; }; 47 | 33A0E83796DA88F4DC8F1B87B3E90A7F /* Pods-LJRouter_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-LJRouter_Example-frameworks.sh"; sourceTree = ""; }; 48 | 3C08F10EA3A8140D98270A2A0C60A9A3 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; 49 | 5055C7A26BFE8346EB06FC9AE2B30A84 /* LJRouterPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LJRouterPrivate.h; path = LJRouter/Core/LJRouterPrivate.h; sourceTree = ""; }; 50 | 5253CBE066A29BEC2D8ED51A7688C504 /* LJRouter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LJRouter.h; path = LJRouter/Core/LJRouter.h; sourceTree = ""; }; 51 | 5C26D5A481D864D7D66AE596AF516E34 /* LJRouter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LJRouter.m; path = LJRouter/Core/LJRouter.m; sourceTree = ""; }; 52 | 725B0B9E990130908A56251D75A483BA /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; 53 | 84BBA6949276A6302B39B74608EC7FEC /* LJRouter-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "LJRouter-prefix.pch"; sourceTree = ""; }; 54 | 869699ECA91E76BDFFD3653A042ECC7B /* LJUrlRouter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LJUrlRouter.m; path = LJRouter/Core/LJUrlRouter.m; sourceTree = ""; }; 55 | 8AEC40840BA9158D5D389CA324D2121C /* Pods-LJRouter_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-LJRouter_Example.debug.xcconfig"; sourceTree = ""; }; 56 | 92BD04E298C527A993D751A7C4E1A4DB /* LJUrlRouter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LJUrlRouter.h; path = LJRouter/Core/LJUrlRouter.h; sourceTree = ""; }; 57 | 9384EA1EC3F9F880AA95D9CAAB2448D8 /* UIViewController+LJNavigation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIViewController+LJNavigation.h"; path = "LJRouter/Navigation/UIViewController+LJNavigation.h"; sourceTree = ""; }; 58 | 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 59 | 979AAAC514FB32C539F5C84B7155C1CC /* Pods-LJRouter_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-LJRouter_Example.release.xcconfig"; sourceTree = ""; }; 60 | 9B149CCA91703BAB29C101853F2D873A /* Pods-LJRouter_Example-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-LJRouter_Example-resources.sh"; sourceTree = ""; }; 61 | AAACCE311E62A263051AB128115292BE /* LJRouter.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = LJRouter.xcconfig; sourceTree = ""; }; 62 | B63C6A64CF66340668996F78DA6BB482 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; 63 | BC58743EFF4E5237B7926C81B6AE3BC4 /* Pods-LJRouter_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-LJRouter_Example-acknowledgements.plist"; sourceTree = ""; }; 64 | C424084C8EE1138C637D11025DC793B1 /* Pods-LJRouter_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-LJRouter_Example-dummy.m"; sourceTree = ""; }; 65 | CB871749505B51AFD97BFC6EB727B6C4 /* LJRouter-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "LJRouter-dummy.m"; sourceTree = ""; }; 66 | CDE6E56A0E64223D07310757724CC6AC /* LJInvocationCenter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LJInvocationCenter.m; path = LJRouter/Core/LJInvocationCenter.m; sourceTree = ""; }; 67 | CE3F4E9A34CAE905CF1E57C8C16D397F /* LJRouterConvertManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LJRouterConvertManager.m; path = LJRouter/Core/LJRouterConvertManager.m; sourceTree = ""; }; 68 | D88AAE1F92055A60CC2FC970D7D34634 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 69 | F11DDBA8BE62EBF7D9BD808D482E89AF /* Pods-LJRouter_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-LJRouter_Example-acknowledgements.markdown"; sourceTree = ""; }; 70 | /* End PBXFileReference section */ 71 | 72 | /* Begin PBXFrameworksBuildPhase section */ 73 | 13A9F228798A263CBD90052D42D1A294 /* Frameworks */ = { 74 | isa = PBXFrameworksBuildPhase; 75 | buildActionMask = 2147483647; 76 | files = ( 77 | 7A40A411BDDC481FE089F9032DA92BCB /* Foundation.framework in Frameworks */, 78 | F9546ED236764DFF2BDFF8BF59EC01A2 /* UIKit.framework in Frameworks */, 79 | ); 80 | runOnlyForDeploymentPostprocessing = 0; 81 | }; 82 | 6E8B39E1293010056503927B3CBAEA3E /* Frameworks */ = { 83 | isa = PBXFrameworksBuildPhase; 84 | buildActionMask = 2147483647; 85 | files = ( 86 | C97CB8CFFDBAEAA0E9367845FAD5094B /* Foundation.framework in Frameworks */, 87 | ); 88 | runOnlyForDeploymentPostprocessing = 0; 89 | }; 90 | /* End PBXFrameworksBuildPhase section */ 91 | 92 | /* Begin PBXGroup section */ 93 | 0486F50E18EADC01A0D32B4277F7EAB1 /* Development Pods */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | 40256EE7B50C4BA7F8A675BCAEA15F8A /* LJRouter */, 97 | ); 98 | name = "Development Pods"; 99 | sourceTree = ""; 100 | }; 101 | 1CDDE9DADB57E938ED5F4CA0C9DBD311 /* Core */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 18D79562941659CE24837C803B462E99 /* LJInvocationCenter.h */, 105 | CDE6E56A0E64223D07310757724CC6AC /* LJInvocationCenter.m */, 106 | 5253CBE066A29BEC2D8ED51A7688C504 /* LJRouter.h */, 107 | 5C26D5A481D864D7D66AE596AF516E34 /* LJRouter.m */, 108 | 3022823B2E59F6312D3679DEC79D2812 /* LJRouterConvertManager.h */, 109 | CE3F4E9A34CAE905CF1E57C8C16D397F /* LJRouterConvertManager.m */, 110 | 5055C7A26BFE8346EB06FC9AE2B30A84 /* LJRouterPrivate.h */, 111 | 92BD04E298C527A993D751A7C4E1A4DB /* LJUrlRouter.h */, 112 | 869699ECA91E76BDFFD3653A042ECC7B /* LJUrlRouter.m */, 113 | 0DC2F486D6A8BCD8F34CE19A2DC87D43 /* metamacros.h */, 114 | ); 115 | name = Core; 116 | sourceTree = ""; 117 | }; 118 | 40256EE7B50C4BA7F8A675BCAEA15F8A /* LJRouter */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 1CDDE9DADB57E938ED5F4CA0C9DBD311 /* Core */, 122 | ED4030E341AA953B088F68AD03BE2E28 /* Navigation */, 123 | 4DC29A2E985102ABF89929CB799C46BA /* Pod */, 124 | 5ADEED61D1E238C3A714D2C1D8538473 /* Support Files */, 125 | ); 126 | name = LJRouter; 127 | path = ../..; 128 | sourceTree = ""; 129 | }; 130 | 433CD3331B6C3787F473C941B61FC68F /* Frameworks */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | 438B396F6B4147076630CAEFE34282C1 /* iOS */, 134 | ); 135 | name = Frameworks; 136 | sourceTree = ""; 137 | }; 138 | 438B396F6B4147076630CAEFE34282C1 /* iOS */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | D88AAE1F92055A60CC2FC970D7D34634 /* Foundation.framework */, 142 | B63C6A64CF66340668996F78DA6BB482 /* UIKit.framework */, 143 | ); 144 | name = iOS; 145 | sourceTree = ""; 146 | }; 147 | 4DC29A2E985102ABF89929CB799C46BA /* Pod */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | 725B0B9E990130908A56251D75A483BA /* LICENSE */, 151 | 2114385887C3BC99E5382E89DB279F5F /* LJRouter.podspec */, 152 | 3C08F10EA3A8140D98270A2A0C60A9A3 /* README.md */, 153 | ); 154 | name = Pod; 155 | sourceTree = ""; 156 | }; 157 | 5ADEED61D1E238C3A714D2C1D8538473 /* Support Files */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | AAACCE311E62A263051AB128115292BE /* LJRouter.xcconfig */, 161 | CB871749505B51AFD97BFC6EB727B6C4 /* LJRouter-dummy.m */, 162 | 84BBA6949276A6302B39B74608EC7FEC /* LJRouter-prefix.pch */, 163 | ); 164 | name = "Support Files"; 165 | path = "Example/Pods/Target Support Files/LJRouter"; 166 | sourceTree = ""; 167 | }; 168 | 69549B099D10D084F39C65CB612EDF2C /* Targets Support Files */ = { 169 | isa = PBXGroup; 170 | children = ( 171 | DACA5DF623DB6EF3F8699DF4EBACB3F1 /* Pods-LJRouter_Example */, 172 | ); 173 | name = "Targets Support Files"; 174 | sourceTree = ""; 175 | }; 176 | 7DB346D0F39D3F0E887471402A8071AB = { 177 | isa = PBXGroup; 178 | children = ( 179 | 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, 180 | 0486F50E18EADC01A0D32B4277F7EAB1 /* Development Pods */, 181 | 433CD3331B6C3787F473C941B61FC68F /* Frameworks */, 182 | D56E717310B2DEF877F1C6850453CE8D /* Products */, 183 | 69549B099D10D084F39C65CB612EDF2C /* Targets Support Files */, 184 | ); 185 | sourceTree = ""; 186 | }; 187 | D56E717310B2DEF877F1C6850453CE8D /* Products */ = { 188 | isa = PBXGroup; 189 | children = ( 190 | 193344E2033F65E4E73190FB2BF8DCBF /* libLJRouter.a */, 191 | 0FB445BF0199E908BD39EB33182BF612 /* libPods-LJRouter_Example.a */, 192 | ); 193 | name = Products; 194 | sourceTree = ""; 195 | }; 196 | DACA5DF623DB6EF3F8699DF4EBACB3F1 /* Pods-LJRouter_Example */ = { 197 | isa = PBXGroup; 198 | children = ( 199 | F11DDBA8BE62EBF7D9BD808D482E89AF /* Pods-LJRouter_Example-acknowledgements.markdown */, 200 | BC58743EFF4E5237B7926C81B6AE3BC4 /* Pods-LJRouter_Example-acknowledgements.plist */, 201 | C424084C8EE1138C637D11025DC793B1 /* Pods-LJRouter_Example-dummy.m */, 202 | 33A0E83796DA88F4DC8F1B87B3E90A7F /* Pods-LJRouter_Example-frameworks.sh */, 203 | 9B149CCA91703BAB29C101853F2D873A /* Pods-LJRouter_Example-resources.sh */, 204 | 8AEC40840BA9158D5D389CA324D2121C /* Pods-LJRouter_Example.debug.xcconfig */, 205 | 979AAAC514FB32C539F5C84B7155C1CC /* Pods-LJRouter_Example.release.xcconfig */, 206 | ); 207 | name = "Pods-LJRouter_Example"; 208 | path = "Target Support Files/Pods-LJRouter_Example"; 209 | sourceTree = ""; 210 | }; 211 | ED4030E341AA953B088F68AD03BE2E28 /* Navigation */ = { 212 | isa = PBXGroup; 213 | children = ( 214 | 9384EA1EC3F9F880AA95D9CAAB2448D8 /* UIViewController+LJNavigation.h */, 215 | 2F713603D0BC5DAC1825045E3C343A24 /* UIViewController+LJNavigation.m */, 216 | ); 217 | name = Navigation; 218 | sourceTree = ""; 219 | }; 220 | /* End PBXGroup section */ 221 | 222 | /* Begin PBXHeadersBuildPhase section */ 223 | 83C5D3210F3CF4FDC085096DB36C51B2 /* Headers */ = { 224 | isa = PBXHeadersBuildPhase; 225 | buildActionMask = 2147483647; 226 | files = ( 227 | E0BE10049AAC2890F685169DBA6ED71F /* LJInvocationCenter.h in Headers */, 228 | 48BF8C7DE9DBE5A20CD338741D476CBA /* LJRouter.h in Headers */, 229 | 729D3AFB73234094614EE8A20C565055 /* LJRouterConvertManager.h in Headers */, 230 | 23570B18BE6B1B9FFC424F8810669353 /* LJRouterPrivate.h in Headers */, 231 | 0083AD54101A8F2BC28D49D9EB763D0B /* LJUrlRouter.h in Headers */, 232 | 665FB8709EB20255F270B3BB34D88B82 /* metamacros.h in Headers */, 233 | 81440BE60992DE7F04E32F4D384C221C /* UIViewController+LJNavigation.h in Headers */, 234 | ); 235 | runOnlyForDeploymentPostprocessing = 0; 236 | }; 237 | /* End PBXHeadersBuildPhase section */ 238 | 239 | /* Begin PBXNativeTarget section */ 240 | 9BE377BC0EA4DBB3AC88A6EA7C749843 /* Pods-LJRouter_Example */ = { 241 | isa = PBXNativeTarget; 242 | buildConfigurationList = FFF5842AA7756556DD07A9693FE51BA1 /* Build configuration list for PBXNativeTarget "Pods-LJRouter_Example" */; 243 | buildPhases = ( 244 | 74701A19B7519A6855751717AE747C0D /* Sources */, 245 | 6E8B39E1293010056503927B3CBAEA3E /* Frameworks */, 246 | ); 247 | buildRules = ( 248 | ); 249 | dependencies = ( 250 | 0DD79F3D5B150FBD99A244FBC7A4C242 /* PBXTargetDependency */, 251 | ); 252 | name = "Pods-LJRouter_Example"; 253 | productName = "Pods-LJRouter_Example"; 254 | productReference = 0FB445BF0199E908BD39EB33182BF612 /* libPods-LJRouter_Example.a */; 255 | productType = "com.apple.product-type.library.static"; 256 | }; 257 | AEE6E99EB3157BC0AFF77C9FE07B7392 /* LJRouter */ = { 258 | isa = PBXNativeTarget; 259 | buildConfigurationList = F6E45B0BA338851D7B9DC734DF017CF1 /* Build configuration list for PBXNativeTarget "LJRouter" */; 260 | buildPhases = ( 261 | 400A04FEA2C569C148F6560B387F67FF /* Sources */, 262 | 13A9F228798A263CBD90052D42D1A294 /* Frameworks */, 263 | 83C5D3210F3CF4FDC085096DB36C51B2 /* Headers */, 264 | ); 265 | buildRules = ( 266 | ); 267 | dependencies = ( 268 | ); 269 | name = LJRouter; 270 | productName = LJRouter; 271 | productReference = 193344E2033F65E4E73190FB2BF8DCBF /* libLJRouter.a */; 272 | productType = "com.apple.product-type.library.static"; 273 | }; 274 | /* End PBXNativeTarget section */ 275 | 276 | /* Begin PBXProject section */ 277 | D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { 278 | isa = PBXProject; 279 | attributes = { 280 | LastSwiftUpdateCheck = 0830; 281 | LastUpgradeCheck = 0700; 282 | }; 283 | buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; 284 | compatibilityVersion = "Xcode 3.2"; 285 | developmentRegion = English; 286 | hasScannedForEncodings = 0; 287 | knownRegions = ( 288 | en, 289 | ); 290 | mainGroup = 7DB346D0F39D3F0E887471402A8071AB; 291 | productRefGroup = D56E717310B2DEF877F1C6850453CE8D /* Products */; 292 | projectDirPath = ""; 293 | projectRoot = ""; 294 | targets = ( 295 | AEE6E99EB3157BC0AFF77C9FE07B7392 /* LJRouter */, 296 | 9BE377BC0EA4DBB3AC88A6EA7C749843 /* Pods-LJRouter_Example */, 297 | ); 298 | }; 299 | /* End PBXProject section */ 300 | 301 | /* Begin PBXSourcesBuildPhase section */ 302 | 400A04FEA2C569C148F6560B387F67FF /* Sources */ = { 303 | isa = PBXSourcesBuildPhase; 304 | buildActionMask = 2147483647; 305 | files = ( 306 | C15B89E3AF780159CA74790D99D19DAE /* LJInvocationCenter.m in Sources */, 307 | 6731DAC759CA8658E123FB13446E536F /* LJRouter-dummy.m in Sources */, 308 | 6D0B910509F817D70D790C8B3805AF36 /* LJRouter.m in Sources */, 309 | 834C0829F0FE1DB8C77F46B8D06ABC05 /* LJRouterConvertManager.m in Sources */, 310 | 68518674328950BAF3BEC991415DEAD9 /* LJUrlRouter.m in Sources */, 311 | 8B0146414ECA1EA9F23A87BCEBDAA59D /* UIViewController+LJNavigation.m in Sources */, 312 | ); 313 | runOnlyForDeploymentPostprocessing = 0; 314 | }; 315 | 74701A19B7519A6855751717AE747C0D /* Sources */ = { 316 | isa = PBXSourcesBuildPhase; 317 | buildActionMask = 2147483647; 318 | files = ( 319 | 1035915AE1C08B61DC1E9EF0E95B1FF8 /* Pods-LJRouter_Example-dummy.m in Sources */, 320 | ); 321 | runOnlyForDeploymentPostprocessing = 0; 322 | }; 323 | /* End PBXSourcesBuildPhase section */ 324 | 325 | /* Begin PBXTargetDependency section */ 326 | 0DD79F3D5B150FBD99A244FBC7A4C242 /* PBXTargetDependency */ = { 327 | isa = PBXTargetDependency; 328 | name = LJRouter; 329 | target = AEE6E99EB3157BC0AFF77C9FE07B7392 /* LJRouter */; 330 | targetProxy = B7187F05F56362033182C1726625EA75 /* PBXContainerItemProxy */; 331 | }; 332 | /* End PBXTargetDependency section */ 333 | 334 | /* Begin XCBuildConfiguration section */ 335 | 01392668EFCA9EFBE01B4FFFD84AD6BB /* Release */ = { 336 | isa = XCBuildConfiguration; 337 | baseConfigurationReference = 979AAAC514FB32C539F5C84B7155C1CC /* Pods-LJRouter_Example.release.xcconfig */; 338 | buildSettings = { 339 | CODE_SIGN_IDENTITY = "iPhone Developer"; 340 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 341 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 342 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 343 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 344 | MACH_O_TYPE = staticlib; 345 | OTHER_LDFLAGS = ""; 346 | OTHER_LIBTOOLFLAGS = ""; 347 | PODS_ROOT = "$(SRCROOT)"; 348 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 349 | SDKROOT = iphoneos; 350 | SKIP_INSTALL = YES; 351 | TARGETED_DEVICE_FAMILY = "1,2"; 352 | VALIDATE_PRODUCT = YES; 353 | }; 354 | name = Release; 355 | }; 356 | 0F6051798894915FAA72FAEBA4BB0132 /* Release */ = { 357 | isa = XCBuildConfiguration; 358 | baseConfigurationReference = AAACCE311E62A263051AB128115292BE /* LJRouter.xcconfig */; 359 | buildSettings = { 360 | CODE_SIGN_IDENTITY = "iPhone Developer"; 361 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 362 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 363 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 364 | GCC_PREFIX_HEADER = "Target Support Files/LJRouter/LJRouter-prefix.pch"; 365 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 366 | OTHER_LDFLAGS = ""; 367 | OTHER_LIBTOOLFLAGS = ""; 368 | PRIVATE_HEADERS_FOLDER_PATH = ""; 369 | PUBLIC_HEADERS_FOLDER_PATH = ""; 370 | SDKROOT = iphoneos; 371 | SKIP_INSTALL = YES; 372 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; 373 | TARGETED_DEVICE_FAMILY = "1,2"; 374 | VALIDATE_PRODUCT = YES; 375 | }; 376 | name = Release; 377 | }; 378 | 1CDAB5613991E411E5990BAF694995C5 /* Debug */ = { 379 | isa = XCBuildConfiguration; 380 | buildSettings = { 381 | ALWAYS_SEARCH_USER_PATHS = NO; 382 | CLANG_ANALYZER_NONNULL = YES; 383 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 384 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 385 | CLANG_CXX_LIBRARY = "libc++"; 386 | CLANG_ENABLE_MODULES = YES; 387 | CLANG_ENABLE_OBJC_ARC = YES; 388 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 389 | CLANG_WARN_BOOL_CONVERSION = YES; 390 | CLANG_WARN_COMMA = YES; 391 | CLANG_WARN_CONSTANT_CONVERSION = YES; 392 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 393 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 394 | CLANG_WARN_EMPTY_BODY = YES; 395 | CLANG_WARN_ENUM_CONVERSION = YES; 396 | CLANG_WARN_INFINITE_RECURSION = YES; 397 | CLANG_WARN_INT_CONVERSION = YES; 398 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 399 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 400 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 401 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 402 | CLANG_WARN_STRICT_PROTOTYPES = YES; 403 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 404 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 405 | CLANG_WARN_UNREACHABLE_CODE = YES; 406 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 407 | CODE_SIGNING_REQUIRED = NO; 408 | COPY_PHASE_STRIP = NO; 409 | DEBUG_INFORMATION_FORMAT = dwarf; 410 | ENABLE_STRICT_OBJC_MSGSEND = YES; 411 | ENABLE_TESTABILITY = YES; 412 | GCC_C_LANGUAGE_STANDARD = gnu11; 413 | GCC_DYNAMIC_NO_PIC = NO; 414 | GCC_NO_COMMON_BLOCKS = YES; 415 | GCC_OPTIMIZATION_LEVEL = 0; 416 | GCC_PREPROCESSOR_DEFINITIONS = ( 417 | "POD_CONFIGURATION_DEBUG=1", 418 | "DEBUG=1", 419 | "$(inherited)", 420 | ); 421 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 422 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 423 | GCC_WARN_UNDECLARED_SELECTOR = YES; 424 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 425 | GCC_WARN_UNUSED_FUNCTION = YES; 426 | GCC_WARN_UNUSED_VARIABLE = YES; 427 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 428 | MTL_ENABLE_DEBUG_INFO = YES; 429 | ONLY_ACTIVE_ARCH = YES; 430 | PRODUCT_NAME = "$(TARGET_NAME)"; 431 | PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; 432 | STRIP_INSTALLED_PRODUCT = NO; 433 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 434 | SYMROOT = "${SRCROOT}/../build"; 435 | }; 436 | name = Debug; 437 | }; 438 | 7B62A85C412D689EF418FA67DA770A41 /* Release */ = { 439 | isa = XCBuildConfiguration; 440 | buildSettings = { 441 | ALWAYS_SEARCH_USER_PATHS = NO; 442 | CLANG_ANALYZER_NONNULL = YES; 443 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 444 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 445 | CLANG_CXX_LIBRARY = "libc++"; 446 | CLANG_ENABLE_MODULES = YES; 447 | CLANG_ENABLE_OBJC_ARC = YES; 448 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 449 | CLANG_WARN_BOOL_CONVERSION = YES; 450 | CLANG_WARN_COMMA = YES; 451 | CLANG_WARN_CONSTANT_CONVERSION = YES; 452 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 453 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 454 | CLANG_WARN_EMPTY_BODY = YES; 455 | CLANG_WARN_ENUM_CONVERSION = YES; 456 | CLANG_WARN_INFINITE_RECURSION = YES; 457 | CLANG_WARN_INT_CONVERSION = YES; 458 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 459 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 460 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 461 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 462 | CLANG_WARN_STRICT_PROTOTYPES = YES; 463 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 464 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 465 | CLANG_WARN_UNREACHABLE_CODE = YES; 466 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 467 | CODE_SIGNING_REQUIRED = NO; 468 | COPY_PHASE_STRIP = NO; 469 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 470 | ENABLE_NS_ASSERTIONS = NO; 471 | ENABLE_STRICT_OBJC_MSGSEND = YES; 472 | GCC_C_LANGUAGE_STANDARD = gnu11; 473 | GCC_NO_COMMON_BLOCKS = YES; 474 | GCC_PREPROCESSOR_DEFINITIONS = ( 475 | "POD_CONFIGURATION_RELEASE=1", 476 | "$(inherited)", 477 | ); 478 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 479 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 480 | GCC_WARN_UNDECLARED_SELECTOR = YES; 481 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 482 | GCC_WARN_UNUSED_FUNCTION = YES; 483 | GCC_WARN_UNUSED_VARIABLE = YES; 484 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 485 | MTL_ENABLE_DEBUG_INFO = NO; 486 | PRODUCT_NAME = "$(TARGET_NAME)"; 487 | PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; 488 | STRIP_INSTALLED_PRODUCT = NO; 489 | SYMROOT = "${SRCROOT}/../build"; 490 | }; 491 | name = Release; 492 | }; 493 | A0A6659BD2C883ADC52FB0FFB96DC083 /* Debug */ = { 494 | isa = XCBuildConfiguration; 495 | baseConfigurationReference = AAACCE311E62A263051AB128115292BE /* LJRouter.xcconfig */; 496 | buildSettings = { 497 | CODE_SIGN_IDENTITY = "iPhone Developer"; 498 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 499 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 500 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 501 | GCC_PREFIX_HEADER = "Target Support Files/LJRouter/LJRouter-prefix.pch"; 502 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 503 | OTHER_LDFLAGS = ""; 504 | OTHER_LIBTOOLFLAGS = ""; 505 | PRIVATE_HEADERS_FOLDER_PATH = ""; 506 | PUBLIC_HEADERS_FOLDER_PATH = ""; 507 | SDKROOT = iphoneos; 508 | SKIP_INSTALL = YES; 509 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; 510 | TARGETED_DEVICE_FAMILY = "1,2"; 511 | }; 512 | name = Debug; 513 | }; 514 | F5472DC2E0D14C0AC6401A886174AEC8 /* Debug */ = { 515 | isa = XCBuildConfiguration; 516 | baseConfigurationReference = 8AEC40840BA9158D5D389CA324D2121C /* Pods-LJRouter_Example.debug.xcconfig */; 517 | buildSettings = { 518 | CODE_SIGN_IDENTITY = "iPhone Developer"; 519 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 520 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 521 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 522 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 523 | MACH_O_TYPE = staticlib; 524 | OTHER_LDFLAGS = ""; 525 | OTHER_LIBTOOLFLAGS = ""; 526 | PODS_ROOT = "$(SRCROOT)"; 527 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 528 | SDKROOT = iphoneos; 529 | SKIP_INSTALL = YES; 530 | TARGETED_DEVICE_FAMILY = "1,2"; 531 | }; 532 | name = Debug; 533 | }; 534 | /* End XCBuildConfiguration section */ 535 | 536 | /* Begin XCConfigurationList section */ 537 | 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { 538 | isa = XCConfigurationList; 539 | buildConfigurations = ( 540 | 1CDAB5613991E411E5990BAF694995C5 /* Debug */, 541 | 7B62A85C412D689EF418FA67DA770A41 /* Release */, 542 | ); 543 | defaultConfigurationIsVisible = 0; 544 | defaultConfigurationName = Release; 545 | }; 546 | F6E45B0BA338851D7B9DC734DF017CF1 /* Build configuration list for PBXNativeTarget "LJRouter" */ = { 547 | isa = XCConfigurationList; 548 | buildConfigurations = ( 549 | A0A6659BD2C883ADC52FB0FFB96DC083 /* Debug */, 550 | 0F6051798894915FAA72FAEBA4BB0132 /* Release */, 551 | ); 552 | defaultConfigurationIsVisible = 0; 553 | defaultConfigurationName = Release; 554 | }; 555 | FFF5842AA7756556DD07A9693FE51BA1 /* Build configuration list for PBXNativeTarget "Pods-LJRouter_Example" */ = { 556 | isa = XCConfigurationList; 557 | buildConfigurations = ( 558 | F5472DC2E0D14C0AC6401A886174AEC8 /* Debug */, 559 | 01392668EFCA9EFBE01B4FFFD84AD6BB /* Release */, 560 | ); 561 | defaultConfigurationIsVisible = 0; 562 | defaultConfigurationName = Release; 563 | }; 564 | /* End XCConfigurationList section */ 565 | }; 566 | rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; 567 | } 568 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/LJRouter/LJRouter-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_LJRouter : NSObject 3 | @end 4 | @implementation PodsDummy_LJRouter 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/LJRouter/LJRouter-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/LJRouter/LJRouter.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/LJRouter 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/LJRouter" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/LJRouter" 4 | OTHER_LDFLAGS = -framework "UIKit" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-LJRouter_Example/Pods-LJRouter_Example-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## LJRouter 5 | 6 | MIT License 7 | 8 | Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in 18 | all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | THE SOFTWARE. 27 | 28 | Generated by CocoaPods - https://cocoapods.org 29 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-LJRouter_Example/Pods-LJRouter_Example-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | MIT License 18 | 19 | Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 20 | 21 | Permission is hereby granted, free of charge, to any person obtaining a copy 22 | of this software and associated documentation files (the "Software"), to deal 23 | in the Software without restriction, including without limitation the rights 24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | copies of the Software, and to permit persons to whom the Software is 26 | furnished to do so, subject to the following conditions: 27 | 28 | The above copyright notice and this permission notice shall be included in 29 | all copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 37 | THE SOFTWARE. 38 | 39 | License 40 | MIT 41 | Title 42 | LJRouter 43 | Type 44 | PSGroupSpecifier 45 | 46 | 47 | FooterText 48 | Generated by CocoaPods - https://cocoapods.org 49 | Title 50 | 51 | Type 52 | PSGroupSpecifier 53 | 54 | 55 | StringsTable 56 | Acknowledgements 57 | Title 58 | Acknowledgements 59 | 60 | 61 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-LJRouter_Example/Pods-LJRouter_Example-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_LJRouter_Example : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_LJRouter_Example 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-LJRouter_Example/Pods-LJRouter_Example-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | # Used as a return value for each invocation of `strip_invalid_archs` function. 10 | STRIP_BINARY_RETVAL=0 11 | 12 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 13 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 14 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 15 | 16 | # Copies and strips a vendored framework 17 | install_framework() 18 | { 19 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 20 | local source="${BUILT_PRODUCTS_DIR}/$1" 21 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 22 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 23 | elif [ -r "$1" ]; then 24 | local source="$1" 25 | fi 26 | 27 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 28 | 29 | if [ -L "${source}" ]; then 30 | echo "Symlinked..." 31 | source="$(readlink "${source}")" 32 | fi 33 | 34 | # Use filter instead of exclude so missing patterns don't throw errors. 35 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 36 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 37 | 38 | local basename 39 | basename="$(basename -s .framework "$1")" 40 | binary="${destination}/${basename}.framework/${basename}" 41 | if ! [ -r "$binary" ]; then 42 | binary="${destination}/${basename}" 43 | fi 44 | 45 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 46 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 47 | strip_invalid_archs "$binary" 48 | fi 49 | 50 | # Resign the code if required by the build settings to avoid unstable apps 51 | code_sign_if_enabled "${destination}/$(basename "$1")" 52 | 53 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 54 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 55 | local swift_runtime_libs 56 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 57 | for lib in $swift_runtime_libs; do 58 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 59 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 60 | code_sign_if_enabled "${destination}/${lib}" 61 | done 62 | fi 63 | } 64 | 65 | # Copies and strips a vendored dSYM 66 | install_dsym() { 67 | local source="$1" 68 | if [ -r "$source" ]; then 69 | # Copy the dSYM into a the targets temp dir. 70 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 71 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 72 | 73 | local basename 74 | basename="$(basename -s .framework.dSYM "$source")" 75 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 76 | 77 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 78 | if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then 79 | strip_invalid_archs "$binary" 80 | fi 81 | 82 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 83 | # Move the stripped file into its final destination. 84 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 85 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 86 | else 87 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 88 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 89 | fi 90 | fi 91 | } 92 | 93 | # Signs a framework with the provided identity 94 | code_sign_if_enabled() { 95 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 96 | # Use the current code_sign_identitiy 97 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 98 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'" 99 | 100 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 101 | code_sign_cmd="$code_sign_cmd &" 102 | fi 103 | echo "$code_sign_cmd" 104 | eval "$code_sign_cmd" 105 | fi 106 | } 107 | 108 | # Strip invalid architectures 109 | strip_invalid_archs() { 110 | binary="$1" 111 | # Get architectures for current target binary 112 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 113 | # Intersect them with the architectures we are building for 114 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 115 | # If there are no archs supported by this binary then warn the user 116 | if [[ -z "$intersected_archs" ]]; then 117 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 118 | STRIP_BINARY_RETVAL=0 119 | return 120 | fi 121 | stripped="" 122 | for arch in $binary_archs; do 123 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 124 | # Strip non-valid architectures in-place 125 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 126 | stripped="$stripped $arch" 127 | fi 128 | done 129 | if [[ "$stripped" ]]; then 130 | echo "Stripped $binary of architectures:$stripped" 131 | fi 132 | STRIP_BINARY_RETVAL=1 133 | } 134 | 135 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 136 | wait 137 | fi 138 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-LJRouter_Example/Pods-LJRouter_Example-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 12 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 13 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 14 | 15 | case "${TARGETED_DEVICE_FAMILY}" in 16 | 1,2) 17 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 18 | ;; 19 | 1) 20 | TARGET_DEVICE_ARGS="--target-device iphone" 21 | ;; 22 | 2) 23 | TARGET_DEVICE_ARGS="--target-device ipad" 24 | ;; 25 | 3) 26 | TARGET_DEVICE_ARGS="--target-device tv" 27 | ;; 28 | 4) 29 | TARGET_DEVICE_ARGS="--target-device watch" 30 | ;; 31 | *) 32 | TARGET_DEVICE_ARGS="--target-device mac" 33 | ;; 34 | esac 35 | 36 | install_resource() 37 | { 38 | if [[ "$1" = /* ]] ; then 39 | RESOURCE_PATH="$1" 40 | else 41 | RESOURCE_PATH="${PODS_ROOT}/$1" 42 | fi 43 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 44 | cat << EOM 45 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 46 | EOM 47 | exit 1 48 | fi 49 | case $RESOURCE_PATH in 50 | *.storyboard) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 53 | ;; 54 | *.xib) 55 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 56 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 57 | ;; 58 | *.framework) 59 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 60 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 61 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 62 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 63 | ;; 64 | *.xcdatamodel) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 67 | ;; 68 | *.xcdatamodeld) 69 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 70 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 71 | ;; 72 | *.xcmappingmodel) 73 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 74 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 75 | ;; 76 | *.xcassets) 77 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 78 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 79 | ;; 80 | *) 81 | echo "$RESOURCE_PATH" || true 82 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 83 | ;; 84 | esac 85 | } 86 | 87 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 88 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 89 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 90 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 91 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 92 | fi 93 | rm -f "$RESOURCES_TO_COPY" 94 | 95 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 96 | then 97 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 98 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 99 | while read line; do 100 | if [[ $line != "${PODS_ROOT}*" ]]; then 101 | XCASSET_FILES+=("$line") 102 | fi 103 | done <<<"$OTHER_XCASSETS" 104 | 105 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 106 | fi 107 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-LJRouter_Example/Pods-LJRouter_Example.debug.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/LJRouter" 3 | LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/LJRouter" 4 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/LJRouter" 5 | OTHER_LDFLAGS = $(inherited) -ObjC -l"LJRouter" -framework "UIKit" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-LJRouter_Example/Pods-LJRouter_Example.release.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/LJRouter" 3 | LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/LJRouter" 4 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/LJRouter" 5 | OTHER_LDFLAGS = $(inherited) -ObjC -l"LJRouter" -framework "UIKit" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /Example/outputHeaders/LJHomeComponentHeader.h: -------------------------------------------------------------------------------- 1 | // 页面 : 首页tabbar 2 | LJRouterUsePage(homeTabbar); 3 | // 页面 : 2017年新版首页 4 | LJRouterUsePage(Home, (NSString*)titlex); 5 | // 页面 : 泛型测试 6 | LJRouterUsePage(objectTypeTest, (NSDictionary*)aaa); 7 | -------------------------------------------------------------------------------- /Example/outputHeaders/LJLoginComponentHeader.h: -------------------------------------------------------------------------------- 1 | // 页面 : 登录页面 2 | LJRouterUsePage(login); 3 | // action : 判断登录状态,弹出登录页面 4 | LJRouterUseAction(loginIfNeed, void, (UIViewController*)curVC, (void(^)(BOOL))finishBlock); 5 | // action : 是否登录状态 6 | LJRouterUseAction(isLogin, BOOL); 7 | // action : 退出登录 8 | LJRouterUseAction(logout, void); 9 | -------------------------------------------------------------------------------- /Example/outputHeaders/LJPersonalComponentHeader.h: -------------------------------------------------------------------------------- 1 | // 页面 : 设置页面 2 | LJRouterUsePage(setting); 3 | // 页面 : 我的个人页 4 | LJRouterUsePage(myProfile, (unsigned long)userId); 5 | // 页面 : 个人页 6 | LJRouterUsePage(myProfile, (NSDictionary*)user); 7 | -------------------------------------------------------------------------------- /Example/outputHeaders/LJWebviewComponentHeader.h: -------------------------------------------------------------------------------- 1 | // 页面 : webview 2 | LJRouterUsePage(webview, (NSString*)url); 3 | // 页面 : webview 4 | LJRouterUsePage(webview, (NSString*)htmlString); 5 | // action : 接收js命令 6 | // 接收一个字符串 添加_haha结尾 7 | LJRouterUseAction(somejscmd, void, (NSString*)str, (LJRouterCallbackBlock)callback); 8 | // action : 设置UIWebView标题 9 | LJRouterUseAction(setWebViewTitle, void, (UIWebView*)sender, (NSString*)title); 10 | // action : 设置UIWebView标题 11 | LJRouterUseAction(setWebViewTitle2, void, (LJRouterSenderContext*)sender, (NSString*)title); 12 | -------------------------------------------------------------------------------- /Example/outputHeaders/action.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "key" : "somejscmd", 4 | "actionDesc" : "接收js命令\/\/ 接收一个字符串 添加_haha结尾", 5 | "parameters" : [ 6 | { 7 | "name" : "str" 8 | }, 9 | { 10 | "name" : "callback" 11 | } 12 | ] 13 | }, 14 | { 15 | "key" : "setWebViewTitle", 16 | "actionDesc" : "设置UIWebView标题", 17 | "parameters" : [ 18 | { 19 | "name" : "sender" 20 | }, 21 | { 22 | "name" : "title" 23 | } 24 | ] 25 | }, 26 | { 27 | "key" : "setWebViewTitle2", 28 | "actionDesc" : "设置UIWebView标题", 29 | "parameters" : [ 30 | { 31 | "name" : "sender" 32 | }, 33 | { 34 | "name" : "title" 35 | } 36 | ] 37 | }, 38 | { 39 | "key" : "loginIfNeed", 40 | "actionDesc" : "判断登录状态,弹出登录页面", 41 | "parameters" : [ 42 | { 43 | "name" : "curVC" 44 | }, 45 | { 46 | "name" : "finishBlock" 47 | } 48 | ] 49 | }, 50 | { 51 | "key" : "isLogin", 52 | "actionDesc" : "是否登录状态", 53 | "parameters" : [ 54 | 55 | ] 56 | }, 57 | { 58 | "key" : "logout", 59 | "actionDesc" : "退出登录", 60 | "parameters" : [ 61 | 62 | ] 63 | } 64 | ] -------------------------------------------------------------------------------- /Example/outputHeaders/page.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "key" : "homeTabbar", 4 | "actionDesc" : "首页tabbar", 5 | "parameters" : [ 6 | 7 | ] 8 | }, 9 | { 10 | "key" : "webview", 11 | "actionDesc" : "webview", 12 | "parameters" : [ 13 | { 14 | "name" : "url" 15 | } 16 | ] 17 | }, 18 | { 19 | "key" : "webview", 20 | "actionDesc" : "webview", 21 | "parameters" : [ 22 | { 23 | "name" : "htmlString" 24 | } 25 | ] 26 | }, 27 | { 28 | "key" : "Home", 29 | "actionDesc" : "2017年新版首页", 30 | "parameters" : [ 31 | { 32 | "name" : "titlex" 33 | } 34 | ] 35 | }, 36 | { 37 | "key" : "objectTypeTest", 38 | "actionDesc" : "泛型测试", 39 | "parameters" : [ 40 | { 41 | "name" : "aaa" 42 | } 43 | ] 44 | }, 45 | { 46 | "key" : "setting", 47 | "actionDesc" : "设置页面", 48 | "parameters" : [ 49 | 50 | ] 51 | }, 52 | { 53 | "key" : "myProfile", 54 | "actionDesc" : "我的个人页", 55 | "parameters" : [ 56 | { 57 | "name" : "userId" 58 | } 59 | ] 60 | }, 61 | { 62 | "key" : "myProfile", 63 | "actionDesc" : "个人页", 64 | "parameters" : [ 65 | { 66 | "name" : "user" 67 | } 68 | ] 69 | }, 70 | { 71 | "key" : "login", 72 | "actionDesc" : "登录页面", 73 | "parameters" : [ 74 | 75 | ] 76 | } 77 | ] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /LJRouter.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'LJRouter' 3 | s.version = '0.7.0' 4 | s.summary = '链家iOS路由方案' 5 | s.description = <<-DESC 6 | LJRouter是链家独立开发完成的ios客户端路由跳转模块,该模块在接入,安全性,易用性都有比较好的表现,一行代码即可支持h5交互,push跳转,url scheme跳转等功能并实时生成文档. 7 | DESC 8 | s.homepage = 'https://github.com/LianjiaTech/LJRouter' 9 | s.license = { :type => 'MIT', :file => 'LICENSE' } 10 | s.author = { 'chenxi' => 'fover0@126.com' } 11 | s.source = { :git => "https://github.com/LianjiaTech/LJRouter.git",:tag => "#{s.version}"} 12 | 13 | s.preserve_path = 'LJRouter/ExportTool','LJRouter/ExportDocument','build' 14 | s.platform = :ios 15 | s.ios.framework = 'UIKit' 16 | s.ios.deployment_target = '8.0' 17 | 18 | s.subspec 'Core' do |ss| 19 | ss.source_files = 'LJRouter/Core/**/*' 20 | end 21 | 22 | s.subspec 'Navigation' do |ss| 23 | ss.source_files = 'LJRouter/Navigation/**/*' 24 | end 25 | 26 | s.default_subspec = 'Core','Navigation' 27 | 28 | end 29 | -------------------------------------------------------------------------------- /LJRouter/Core/LJInvocationCenter.h: -------------------------------------------------------------------------------- 1 | // 2 | // LJInvocationCenter.h 3 | // IM 4 | // 5 | // Created by fover0 on 2017/5/28. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | #import 10 | #import "LJRouterConvertManager.h" 11 | 12 | 13 | // 参数描述 14 | @interface LJInvocationCenterItemParam : NSObject 15 | 16 | @property (nonatomic, readonly) BOOL isRequire; 17 | @property (nonatomic, readonly) NSString *name; 18 | @property (nonatomic, readonly) NSString *typeName; 19 | @property (nonatomic, readonly) NSString *typeEncoding; 20 | @property (nonatomic, readonly) id info; 21 | 22 | // lazy create NSArray* objcClass is NSArray objectTypes is [NSString] 23 | @property (nonatomic, readonly) Class objcClass; 24 | @property (nonatomic, readonly) NSArray *objectTypes; 25 | 26 | 27 | - (instancetype)initWithName:(NSString*)name 28 | typeName:(NSString*)typeName 29 | typeEncoding:(NSString*)typeEncoding 30 | isRequire:(BOOL)isRequire 31 | info:(id)info; 32 | @end 33 | 34 | // 函数重载描述 35 | @interface LJInvocationCenterItemRule : NSObject 36 | @property (nonatomic, readonly) SEL selector; 37 | @property (nonatomic, readonly) NSString *returnTypeName; 38 | @property (nonatomic, readonly) NSString *returnTypeEncoding; 39 | @property (nonatomic, readonly) NSArray* paramas; 40 | 41 | - (instancetype)initWithSelector:(SEL)selector 42 | returnTypeName:(NSString*)returnTypeName 43 | returnTypeEncoding:(NSString*)returnTypeEncoding 44 | params:(NSArray*)params; 45 | 46 | @end 47 | 48 | // 函数描述 49 | @interface LJInvocationCenterItem : NSObject 50 | 51 | @property (nonatomic, readonly) NSString *key; 52 | @property (nonatomic, readonly) id target; 53 | @property (nonatomic, readonly) NSArray *rules; 54 | 55 | @end 56 | 57 | // 转发中心 58 | @interface LJInvocationCenter : NSObject 59 | 60 | @property (nonatomic, retain) LJRouterConvertManager *convertManager; 61 | 62 | - (LJInvocationCenterItem*)getInvocationCenterItemByKey:(NSString*)key; 63 | 64 | - (void)addInvocationWithKey:(NSString*)key 65 | target:(id)target 66 | rule:(LJInvocationCenterItemRule*)rule; 67 | 68 | - (NSInvocation*)invocationWithKey:(NSString*)key 69 | data:(NSDictionary*)data 70 | outItem:(LJInvocationCenterItem**)outItem 71 | outRule:(LJInvocationCenterItemRule**)outRule; 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /LJRouter/Core/LJInvocationCenter.m: -------------------------------------------------------------------------------- 1 | // 2 | // LJInvocationCenter.m 3 | // IM 4 | // 5 | // Created by fover0 on 2017/5/28. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | #import "LJInvocationCenter.h" 10 | #import 11 | #import 12 | 13 | @interface LJInvocationCenterItemParam() 14 | { 15 | BOOL _classLazyLoadFinish; 16 | } 17 | @end 18 | 19 | @implementation LJInvocationCenterItemParam 20 | @synthesize objcClass = _objcClass; 21 | @synthesize objectTypes = _objectTypes; 22 | 23 | - (instancetype)initWithName:(NSString *)name 24 | typeName:(NSString *)typpName 25 | typeEncoding:(NSString *)typeEncoding 26 | isRequire:(BOOL)isRequire 27 | info:(id)info 28 | { 29 | self = [super init]; 30 | if (self) 31 | { 32 | _classLazyLoadFinish = NO; 33 | _name = [name copy]; 34 | _typeName = [typpName copy]; 35 | _typeEncoding = [typeEncoding copy]; 36 | _isRequire = isRequire; 37 | _info = info; 38 | 39 | _objcClass = Nil; 40 | _objectTypes = nil; 41 | } 42 | return self; 43 | } 44 | 45 | - (void)findObjectTypesInString:(NSString*)str 46 | outTypeNames:(NSArray**)outTypeNames 47 | outTypeEncoding:(NSArray**)outTypeEncodings 48 | { 49 | NSRange range; 50 | NSInteger stackCount = 0; 51 | NSInteger beginIndex = 0; 52 | NSString *typeEncoding = @"@"; 53 | NSMutableArray *_outTypeNames = nil; 54 | NSMutableArray *_outTypeEncodings = nil; 55 | for(int i = 0 ; i < str.length; i += range.length) 56 | { 57 | range = [str rangeOfComposedCharacterSequenceAtIndex:i]; 58 | if (range.length == 1) 59 | { 60 | NSString *s = [str substringWithRange:range]; 61 | if ([s isEqualToString:@"<"] 62 | || [s isEqualToString:@"("] 63 | || [s isEqualToString:@"["] 64 | || [s isEqualToString:@"{"]) 65 | { 66 | stackCount ++; 67 | } 68 | if ([s isEqualToString:@">"] 69 | || [s isEqualToString:@")"] 70 | || [s isEqualToString:@"]"] 71 | || [s isEqualToString:@"}"]) 72 | { 73 | stackCount --; 74 | } 75 | 76 | if (stackCount == 0) 77 | { 78 | NSString *typeName = nil; 79 | if ([s isEqualToString:@","]) 80 | { 81 | typeName = [str substringWithRange:NSMakeRange(beginIndex, range.location - beginIndex)]; 82 | 83 | 84 | } 85 | else if (range.length + range.location == str.length) 86 | { 87 | typeName = [str substringFromIndex:beginIndex]; 88 | } 89 | else if ([s isEqualToString:@"^"]) 90 | { 91 | typeEncoding = @"?"; 92 | } 93 | 94 | if (typeName) 95 | { 96 | if (!_outTypeNames) 97 | { 98 | _outTypeNames = [[NSMutableArray alloc] init]; 99 | _outTypeEncodings = [[NSMutableArray alloc] init]; 100 | if (outTypeNames) 101 | { 102 | *outTypeNames = _outTypeNames; 103 | *outTypeEncodings = _outTypeEncodings; 104 | } 105 | } 106 | [_outTypeNames addObject:typeName]; 107 | [_outTypeEncodings addObject:typeEncoding]; 108 | typeEncoding = @"@"; 109 | beginIndex = range.location + 1; 110 | } 111 | } 112 | } 113 | } 114 | } 115 | 116 | 117 | - (void)lazyloadClassAndObjectTypes 118 | { 119 | if (_classLazyLoadFinish) 120 | { 121 | return; 122 | } 123 | @synchronized(self) { 124 | if (_classLazyLoadFinish) 125 | { 126 | return; 127 | } 128 | 129 | if (![self.typeEncoding isEqualToString:@"@"]) 130 | { 131 | return; 132 | } 133 | 134 | NSMutableArray *objectTypesArray = nil; 135 | 136 | NSRange range = [self.typeName rangeOfString:@"<"]; 137 | if (range.length) 138 | { 139 | NSRange endRange = [self.typeName rangeOfString:@">" options:NSBackwardsSearch]; 140 | if (endRange.length) 141 | { 142 | NSString *startStr = [self.typeName substringToIndex:range.location]; 143 | _objcClass = NSClassFromString(startStr); 144 | if (_objcClass) 145 | { 146 | NSString *objectTypesString = [self.typeName substringWithRange:NSMakeRange(range.location + 1, endRange.location - range.location - 1 )]; 147 | NSArray *typeNames = nil; 148 | NSArray *typeEncoding = nil; 149 | [self findObjectTypesInString:objectTypesString 150 | outTypeNames:&typeNames 151 | outTypeEncoding:&typeEncoding]; 152 | for (NSInteger i = 0 ; i < typeNames.count ; i ++) 153 | { 154 | LJInvocationCenterItemParam *param = 155 | [[LJInvocationCenterItemParam alloc] initWithName:@"" 156 | typeName:typeNames[i] 157 | typeEncoding:typeEncoding[i] 158 | isRequire:self.isRequire 159 | info:self.info]; 160 | if (objectTypesArray == nil) 161 | { 162 | objectTypesArray = [[NSMutableArray alloc] init]; 163 | _objectTypes = objectTypesArray; 164 | } 165 | [objectTypesArray addObject:param]; 166 | } 167 | } 168 | } 169 | } 170 | else 171 | { 172 | NSString *className = [self.typeName stringByReplacingOccurrencesOfString:@" " withString:@""]; 173 | className = [className stringByReplacingOccurrencesOfString:@"*" withString:@""]; 174 | _objcClass = NSClassFromString(className); 175 | } 176 | _classLazyLoadFinish = YES; 177 | } 178 | } 179 | 180 | - (Class)objcClass 181 | { 182 | [self lazyloadClassAndObjectTypes]; 183 | return _objcClass; 184 | } 185 | 186 | - (NSArray*)objectTypes 187 | { 188 | [self lazyloadClassAndObjectTypes]; 189 | return _objectTypes; 190 | } 191 | 192 | @end 193 | 194 | @implementation LJInvocationCenterItemRule 195 | 196 | - (instancetype)initWithSelector:(SEL)selector 197 | returnTypeName:(NSString *)returnTypeName 198 | returnTypeEncoding:(NSString *)returnTypeEncoding 199 | params:(NSArray *)params{ 200 | self = [super init]; 201 | if (self) 202 | { 203 | _selector = selector; 204 | _returnTypeName = [returnTypeName copy]; 205 | _returnTypeEncoding = [returnTypeEncoding copy]; 206 | _paramas = params; 207 | 208 | } 209 | return self; 210 | } 211 | 212 | @end 213 | 214 | @interface LJInvocationCenterItem() 215 | { 216 | NSMutableArray* _rules; 217 | __unsafe_unretained id unsafeTarget; 218 | id safeTarget; 219 | } 220 | 221 | @end 222 | 223 | @implementation LJInvocationCenterItem 224 | 225 | - (NSArray*)rules 226 | { 227 | return _rules; 228 | } 229 | 230 | - (instancetype)initWithKey:(NSString*)key target:(__unsafe_unretained id)target 231 | { 232 | self = [super init]; 233 | if (self) 234 | { 235 | _rules = [[NSMutableArray alloc] init]; 236 | _key = [key copy]; 237 | 238 | Dl_info dlInfo; 239 | memset(&dlInfo, 0, sizeof(Dl_info)); 240 | dladdr((__bridge void*)target, &dlInfo); 241 | if (object_isClass(target) && dlInfo.dli_fbase != 0) 242 | { 243 | unsafeTarget = target; 244 | safeTarget = Nil; 245 | } 246 | else 247 | { 248 | unsafeTarget = Nil; 249 | safeTarget = target; 250 | } 251 | } 252 | return self; 253 | } 254 | 255 | - (id)target 256 | { 257 | return unsafeTarget ? unsafeTarget : safeTarget; 258 | } 259 | 260 | - (void)addRule:(LJInvocationCenterItemRule*)rule 261 | { 262 | [_rules addObject:rule]; 263 | } 264 | 265 | @end 266 | 267 | @interface LJInvocationCenter() 268 | 269 | @property (nonatomic, retain) NSMutableDictionary *allItem; 270 | 271 | @end 272 | 273 | @implementation LJInvocationCenter 274 | 275 | - (instancetype)init 276 | { 277 | self = [super init]; 278 | if (self) 279 | { 280 | self.allItem = [[NSMutableDictionary alloc] init]; 281 | } 282 | return self; 283 | } 284 | - (void)addInvocationWithKey:(NSString *)key 285 | target:(__unsafe_unretained id)target 286 | rule:(LJInvocationCenterItemRule *)rule 287 | { 288 | if (!key.length || !target || !rule || !rule.selector || !rule.returnTypeName.length ) 289 | { 290 | return; 291 | } 292 | 293 | 294 | 295 | 296 | // 一共分三种情况 297 | LJInvocationCenterItem *item = self.allItem[key]; 298 | 299 | // 1.直接添加 300 | if (!item) 301 | { 302 | item = [[LJInvocationCenterItem alloc] initWithKey:key target:target]; 303 | [item addRule:rule]; 304 | self.allItem[key] = item; 305 | } 306 | // 2.相同target 307 | else if (item.target == target) 308 | { 309 | for (LJInvocationCenterItemRule *registedRule in item.rules) 310 | { 311 | // 和已有的rule冲突失败 312 | if (registedRule.selector == rule.selector) 313 | { 314 | return; 315 | } 316 | } 317 | [item addRule:rule]; 318 | } 319 | else 320 | { 321 | NSLog(@"页面 %@ 与 页面 %@ 同时注册了 key:\"%@\"",item.target,target,key); 322 | assert(0); 323 | } 324 | } 325 | 326 | - (NSInvocation*)invocationForTarget:(id)target rule:(LJInvocationCenterItemRule*)rule data:(NSDictionary*)data 327 | { 328 | NSMutableArray *paramValues = [[NSMutableArray alloc] init]; 329 | for (LJInvocationCenterItemParam *param in rule.paramas) 330 | { 331 | id value = [data valueForKey:param.name]; 332 | if (!value && param.isRequire) 333 | { 334 | return nil; 335 | } 336 | [paramValues addObject:value?:[NSNull null]]; 337 | } 338 | 339 | Class clazz = object_getClass(target); 340 | Method method = class_getInstanceMethod(clazz, rule.selector); 341 | 342 | NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:method_getTypeEncoding(method)]; 343 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; 344 | invocation.target = target; 345 | invocation.selector = rule.selector; 346 | 347 | 348 | 349 | NSMutableArray *allInvokeValue = nil; 350 | for (NSInteger idx = 0 ; idx < paramValues.count ; idx ++) 351 | { 352 | id obj = paramValues[idx]; 353 | if (obj == [NSNull null]) 354 | { 355 | continue; 356 | } 357 | LJInvocationCenterItemParam *param = rule.paramas[idx]; 358 | 359 | LJRouterConvertInvokeValue *invokeValue = [self.convertManager invokeValueWithJson:obj param:param]; 360 | 361 | if (invokeValue) 362 | { 363 | [invocation setArgument:invokeValue.result atIndex:idx+2]; 364 | if (!allInvokeValue) 365 | { 366 | allInvokeValue = [[NSMutableArray alloc] init]; 367 | static char someKey; 368 | objc_setAssociatedObject(invocation, &someKey , allInvokeValue, OBJC_ASSOCIATION_RETAIN); 369 | } 370 | [allInvokeValue addObject:invokeValue]; 371 | } 372 | else 373 | { 374 | [invocation setArgument:(void*)&obj atIndex:idx + 2]; 375 | } 376 | } 377 | 378 | return invocation; 379 | } 380 | 381 | - (void)runInvocation:(NSInvocation*)invocation 382 | { 383 | [invocation invoke]; 384 | } 385 | 386 | - (NSInvocation*)invocationWithKey:(NSString *)key 387 | data:(NSDictionary *)data 388 | outItem:(LJInvocationCenterItem *__autoreleasing *)outItem 389 | outRule:(LJInvocationCenterItemRule *__autoreleasing *)outRule 390 | { 391 | LJInvocationCenterItem *item = self.allItem[key]; 392 | for (LJInvocationCenterItemRule *rule in item.rules) 393 | { 394 | NSInvocation *invocation = [self invocationForTarget:item.target rule:rule data:data]; 395 | if (invocation) 396 | { 397 | if (outItem) 398 | { 399 | *outItem = item; 400 | } 401 | if (outRule) 402 | { 403 | *outRule = rule; 404 | } 405 | return invocation; 406 | } 407 | } 408 | return nil; 409 | } 410 | 411 | - (LJInvocationCenterItem*)getInvocationCenterItemByKey:(NSString*)key 412 | { 413 | return [self.allItem valueForKey:key]; 414 | } 415 | 416 | @end 417 | -------------------------------------------------------------------------------- /LJRouter/Core/LJRouter.h: -------------------------------------------------------------------------------- 1 | // 2 | // LJRouter.h 3 | // invocation 4 | // 5 | // Created by fover0 on 2017/5/28. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | #import 10 | #import "LJInvocationCenter.h" 11 | #import "LJRouterConvertManager.h" 12 | 13 | typedef NS_ENUM(NSUInteger, LJRouterCheckPolicy) { 14 | LJRouterCheckPolicyAssert = 0, // default 15 | LJRouterCheckPolicyConsole = 1, 16 | LJRouterCheckPolicyAlert = 2, 17 | }; 18 | 19 | typedef void(^LJRouterCallbackBlock)(NSString* mess,BOOL complete); 20 | 21 | @interface LJRouter : NSObject 22 | 23 | @property (nonatomic, readonly) LJRouterConvertManager *convertManager; 24 | 25 | // 初始化 26 | + (instancetype)sharedInstance; 27 | - (instancetype)init __deprecated; 28 | 29 | // router 30 | - (BOOL)canRouterKey:(NSString*)key data:(NSDictionary*)data; 31 | - (BOOL)routerKey:(NSString*)key 32 | data:(NSDictionary*)data 33 | sender:(UIResponder*)sender 34 | pageBlock:(void(^)(__kindof UIViewController* viewController))pageBlock 35 | callbackBlock:(void(^)(NSString* key,NSString *value,NSString* data,BOOL complete))callbackBlock 36 | canNotRouterBlock:(void(^)(void))canNotRouterBlock; 37 | 38 | - (void)openViewController:(UIViewController*)vc withSender:(id)sender; 39 | 40 | @end 41 | 42 | @interface LJRouterSenderContext : NSObject 43 | 44 | // 原始sender 45 | @property (nonatomic, readonly) UIResponder *originSender; 46 | 47 | // 以下函数 会按照originSender本身以及nextResponder依次寻找命中该类型的对象 48 | @property (nonatomic, readonly) UIView *contextView; 49 | @property (nonatomic, readonly) UIViewController *contextViewController; 50 | @property (nonatomic, readonly) UIWindow *contextWindow; 51 | @property (nonatomic, readonly) id contextAppDelegate; 52 | @property (nonatomic, readonly) UIApplication *contextAppliaction; 53 | 54 | @end 55 | 56 | 57 | @interface LJRouter(config) 58 | 59 | // 默认为nil , nil与@[]时检查所有模块 60 | @property (nonatomic, retain) NSArray *checkPolicyModules; 61 | @property (nonatomic, assign) LJRouterCheckPolicy checkPolicy; 62 | 63 | @property (nonatomic, copy) void(^openControllerBlock)(UIViewController*vc,id sender) __deprecated_msg("请使用openControllerWithContextBlock"); 64 | @property (nonatomic, copy) void(^openControllerWithContextBlock)(UIViewController*vc, LJRouterSenderContext *senderContext); 65 | 66 | @end 67 | 68 | @interface UIViewController(LJRouter) 69 | 70 | // 属性是通过实例调用 如果该页面通过路由产生 则会返回该次路由所使用的key 71 | // 请不要直接设置该属性 72 | @property (nonatomic, copy) NSString *ljRouterKey; 73 | @end 74 | 75 | 76 | 77 | #import "LJRouterPrivate.h" 78 | -------------------------------------------------------------------------------- /LJRouter/Core/LJRouter.m: -------------------------------------------------------------------------------- 1 | // 2 | // LJRouter.m 3 | // invocation 4 | // 5 | // Created by fover0 on 2017/5/28. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #import 13 | #import 14 | 15 | #ifndef __LP64__ 16 | #define section_ section 17 | #define mach_header_ mach_header 18 | #else 19 | #define section_ section_64 20 | #define mach_header_ mach_header_64 21 | #endif 22 | 23 | #import "LJRouter.h" 24 | #import "LJInvocationCenter.h" 25 | 26 | 27 | #define LJRouterCallbackBlockName @"LJRouterCallbackBlock" 28 | 29 | @implementation UIViewController(LJRouter) 30 | 31 | static char ljRouterKeyKey; 32 | - (void)setLjRouterKey:(NSString *)ljRouterKey 33 | { 34 | objc_setAssociatedObject(self, &ljRouterKeyKey, [ljRouterKey copy], OBJC_ASSOCIATION_RETAIN); 35 | } 36 | 37 | - (NSString*)ljRouterKey 38 | { 39 | return objc_getAssociatedObject(self, &ljRouterKeyKey); 40 | } 41 | 42 | @end 43 | 44 | @interface LJRouterSenderContext() 45 | 46 | // 原始sender 47 | @property (nonatomic, retain) UIResponder *originSender; 48 | 49 | // 以下函数 会按照originSender本身以及nextResponder依次寻找命中该类型的对象 50 | @property (nonatomic, retain) UIView *contextView; 51 | @property (nonatomic, retain) UIViewController *contextViewController; 52 | @property (nonatomic, retain) UIWindow *contextWindow; 53 | @property (nonatomic, retain) id contextAppDelegate; 54 | @property (nonatomic, retain) UIApplication *contextAppliaction; 55 | 56 | @end 57 | 58 | @implementation LJRouterSenderContext 59 | 60 | - (instancetype)initWithSender:(UIResponder*)sender 61 | { 62 | self = [super init]; 63 | if (self) 64 | { 65 | self.originSender = sender; 66 | [self loadResponderWithSender:sender]; 67 | } 68 | return self; 69 | } 70 | 71 | - (void)loadResponderWithSender:(UIResponder*)sender 72 | { 73 | UIResponder *r = sender; 74 | while (r) { 75 | if ([r isKindOfClass:[UIView class]]) 76 | { 77 | if (!_contextView) 78 | { 79 | _contextView = (UIView*)r; 80 | _contextWindow = _contextView.window; 81 | } 82 | } 83 | else if ([r isKindOfClass:[UIViewController class]]) 84 | { 85 | if (!_contextViewController) 86 | { 87 | _contextViewController = (UIViewController*)r; 88 | } 89 | } 90 | else if ([r isKindOfClass:[UIApplication class]]) 91 | { 92 | if (!_contextAppliaction) 93 | { 94 | _contextAppliaction = (UIApplication*)r; 95 | _contextAppDelegate = _contextAppliaction.delegate; 96 | } 97 | } 98 | 99 | r = r.nextResponder; 100 | } 101 | } 102 | 103 | @end 104 | 105 | 106 | @interface LJRouter () 107 | { 108 | void(^_openControllerBlock)(UIViewController*vc,id sender); 109 | void(^_openControllerWithSenderBlock)(UIViewController*vc,LJRouterSenderContext *senderContext); 110 | LJRouterCheckPolicy _checkPolicy; 111 | NSArray *_checkPolicyModules; 112 | } 113 | 114 | @property (nonatomic, retain) LJInvocationCenter *pageInvocationCenter; 115 | @property (nonatomic, retain) LJInvocationCenter *actionInvocationCenter; 116 | @end 117 | 118 | static NSMutableDictionary *allKeyMethods = nil; 119 | 120 | @implementation LJRouter 121 | 122 | @synthesize convertManager = _convertManager; 123 | 124 | + (instancetype)sharedInstance 125 | { 126 | static id instance = nil; 127 | static dispatch_once_t onceToken; 128 | dispatch_once(&onceToken, ^{ 129 | instance = [[self alloc] initPrivate]; 130 | }); 131 | return instance; 132 | } 133 | 134 | - (void)loadAllPageProperty 135 | { 136 | LJRouterConvertManager *convertManager = [[LJRouterConvertManager alloc] init]; 137 | _convertManager = convertManager; 138 | 139 | LJInvocationCenter *pageCenter = [[LJInvocationCenter alloc] init]; 140 | _pageInvocationCenter = pageCenter; 141 | _pageInvocationCenter.convertManager = convertManager; 142 | 143 | LJInvocationCenter *actionCenter = [[LJInvocationCenter alloc] init]; 144 | _actionInvocationCenter = actionCenter; 145 | _actionInvocationCenter.convertManager = convertManager; 146 | 147 | uint32_t count = _dyld_image_count(); 148 | for (uint32_t i = 0 ; i < count ; i++) 149 | { 150 | const struct mach_header_* header = (void*)_dyld_get_image_header(i); 151 | unsigned long size = 0; 152 | // 注册所有的vc 153 | uint8_t *data = getsectiondata(header, "__DATA", "__LJRouter",&size); 154 | if (data && size > 0) 155 | { 156 | struct LJRouterRegister *items = (struct LJRouterRegister*)data; 157 | uint32_t count = (uint32_t)(size / sizeof(struct LJRouterRegister)); 158 | for (uint32_t i = 0 ; i < count ; i ++) 159 | { 160 | NSMutableString *methodKeyTypeVarName = [[NSMutableString alloc] initWithString:items[i].returnTypeName]; 161 | NSMutableArray *params = nil; 162 | if (items[i].paramscount) 163 | { 164 | params = [[NSMutableArray alloc] init]; 165 | for (uint32_t j = 0 ; j < items[i].paramscount ; j ++) 166 | { 167 | BOOL isRequire = items[i].params[j].isRequire; 168 | if ([items[i].params[j].typeName isEqualToString:LJRouterCallbackBlockName]) 169 | { 170 | isRequire = NO; 171 | } 172 | 173 | LJInvocationCenterItemParam *param = 174 | [[LJInvocationCenterItemParam alloc] initWithName:items[i].params[j].name.lowercaseString 175 | typeName:items[i].params[j].typeName 176 | typeEncoding:[NSString stringWithFormat:@"%s",items[i].params[j].typeEncoding] 177 | isRequire:isRequire 178 | info:nil]; 179 | 180 | [params addObject:param]; 181 | 182 | [methodKeyTypeVarName appendString:items[i].params[j].typeName]; 183 | [methodKeyTypeVarName appendString:items[i].params[j].name]; 184 | } 185 | } 186 | 187 | NSMutableArray *methodNames = allKeyMethods[items[i].key.lowercaseString]; 188 | if (!methodNames) 189 | { 190 | methodNames = [[NSMutableArray alloc] init]; 191 | allKeyMethods[items[i].key.lowercaseString] = methodNames; 192 | } 193 | [methodNames addObject:[methodKeyTypeVarName stringByReplacingOccurrencesOfString:@" " withString:@""]]; 194 | 195 | LJInvocationCenter *center = items[i].isAction ? actionCenter : pageCenter; 196 | 197 | NSString *functionName = [[NSString alloc] initWithUTF8String:items[i].objcFunctionName]; 198 | NSRange range = [functionName rangeOfString:@" "]; 199 | NSString *className = [functionName substringWithRange:NSMakeRange(2, range.location - 2)]; 200 | range = [className rangeOfString:@"("]; 201 | if (range.length) 202 | { 203 | className = [className substringToIndex:range.location]; 204 | } 205 | 206 | LJInvocationCenterItemRule *rule = 207 | [[LJInvocationCenterItemRule alloc] initWithSelector:NSSelectorFromString(items[i].selName) 208 | returnTypeName:items[i].returnTypeName 209 | returnTypeEncoding:[NSString stringWithUTF8String:items[i].returnTypeEncoding] 210 | params:params]; 211 | 212 | [center addInvocationWithKey:items[i].key.lowercaseString 213 | target:NSClassFromString(className) 214 | rule:rule]; 215 | } 216 | break; 217 | } 218 | } 219 | } 220 | 221 | BOOL LJRouterCheckMethodType(NSString *key, 222 | NSString *returnTypeName, 223 | struct LJRouterRegisterParam* originParams, 224 | uint32_t paramsCount, 225 | NSString **errorMessage) 226 | { 227 | NSMutableString *methodName = [[NSMutableString alloc] initWithString:returnTypeName]; 228 | for (uint32_t i = 0 ; i < paramsCount ; i++) 229 | { 230 | struct LJRouterRegisterParam *param = originParams + i; 231 | [methodName appendString:param->typeName]; 232 | [methodName appendString:param->name]; 233 | } 234 | NSString *methodNameComp = [methodName stringByReplacingOccurrencesOfString:@" " withString:@""]; 235 | 236 | NSArray *methodNamesArray = [allKeyMethods valueForKey:key.lowercaseString]; 237 | for (NSString *name in methodNamesArray) 238 | { 239 | if ([name isEqualToString:methodNameComp]) 240 | { 241 | return YES; 242 | } 243 | } 244 | if (errorMessage) 245 | { 246 | *errorMessage = @"参数类型或变量名不匹配,请检查"; 247 | } 248 | 249 | return NO; 250 | 251 | } 252 | 253 | - (BOOL)checkInModules:(NSString*)filePath 254 | { 255 | if (self.checkPolicyModules.count == 0) 256 | { 257 | return YES; 258 | } 259 | 260 | NSArray *paths = [filePath componentsSeparatedByString:@"/"]; 261 | for (NSString *path in paths) 262 | { 263 | for (NSString *module in self.checkPolicyModules) 264 | { 265 | if ([path isEqualToString:module]) 266 | { 267 | return YES; 268 | } 269 | } 270 | } 271 | return NO; 272 | } 273 | 274 | - (void)checkAllMethodTypeName 275 | { 276 | uint32_t count = _dyld_image_count(); 277 | for (uint32_t i = 0 ; i < count ; i++) 278 | { 279 | const struct mach_header_* header = (void*)_dyld_get_image_header(i); 280 | unsigned long size = 0; 281 | // 检查所有的函数类型 282 | uint8_t *data = getsectiondata(header, "__DATA", "__LJRouterUseINF",&size); 283 | if (data && size > 0) 284 | { 285 | struct LJRouterUseInfo* infos = (void*)data; 286 | uint32_t count = (uint32_t)(size / sizeof(struct LJRouterUseInfo)); 287 | NSMutableString *alertMessage = nil; 288 | for (uint32_t i = 0 ; i < count ; i ++) 289 | { 290 | struct LJRouterUseInfo *info = infos + i; 291 | NSString *filePath = [NSString stringWithUTF8String:info->filePath]; 292 | if (![self checkInModules:filePath]) 293 | { 294 | continue; 295 | } 296 | 297 | NSString *message = nil; 298 | BOOL check = 299 | LJRouterCheckMethodType(info->key, 300 | info->returnTypeName, 301 | info->params, 302 | info->paramCount, 303 | &message); 304 | if (!check) 305 | { 306 | if (self.checkPolicy == LJRouterCheckPolicyAssert) 307 | { 308 | void** addr = (void**)info->assertBlock; 309 | void(^block)(NSString*) = (__bridge id)*addr; 310 | block(message); 311 | } 312 | else if (self.checkPolicy == LJRouterCheckPolicyConsole) 313 | { 314 | NSLog(@"文件 %s 行号 %llu",info->filePath,info->lineNumber); 315 | } 316 | else if (self.checkPolicy == LJRouterCheckPolicyAlert) 317 | { 318 | if (!alertMessage) 319 | { 320 | alertMessage = [[NSMutableString alloc] init]; 321 | } 322 | 323 | NSString *file = [[NSString alloc] initWithUTF8String:info->filePath]; 324 | NSArray *comp = [file componentsSeparatedByString:@"/"]; 325 | 326 | [alertMessage appendFormat:@"%@:%llu %@\n",comp.lastObject,info->lineNumber,info->key]; 327 | } 328 | } 329 | } 330 | if (alertMessage.length) 331 | { 332 | UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"校验错误" message:alertMessage delegate:nil cancelButtonTitle:@"知道了" otherButtonTitles:nil]; 333 | [alertView show]; 334 | } 335 | } 336 | } 337 | } 338 | 339 | - (instancetype)initPrivate 340 | { 341 | self = [super init]; 342 | if (self) 343 | { 344 | _openControllerBlock = nil; 345 | allKeyMethods = [[NSMutableDictionary alloc] init]; 346 | _checkPolicy = LJRouterCheckPolicyAssert; 347 | _checkPolicyModules = nil; 348 | } 349 | return self; 350 | } 351 | 352 | - (void)loadAndCheck 353 | { 354 | static dispatch_once_t onceToken; 355 | dispatch_once(&onceToken, ^{ 356 | [self loadAllPageProperty]; 357 | [self checkAllMethodTypeName]; 358 | }); 359 | } 360 | 361 | - (LJInvocationCenter*)actionInvocationCenter 362 | { 363 | [self loadAndCheck]; 364 | return _actionInvocationCenter; 365 | } 366 | 367 | - (LJInvocationCenter*)pageInvocationCenter 368 | { 369 | [self loadAndCheck]; 370 | return _pageInvocationCenter; 371 | } 372 | 373 | - (LJRouterConvertManager*)convertManager 374 | { 375 | [self loadAndCheck]; 376 | return _convertManager; 377 | } 378 | 379 | - (instancetype)init 380 | { 381 | return [[self class] sharedInstance]; 382 | } 383 | 384 | - (BOOL)canRouterKey:(NSString *)key data:(NSDictionary *)data 385 | { 386 | NSInvocation *pageInvocation = 387 | [self.pageInvocationCenter invocationWithKey:key.lowercaseString 388 | data:data 389 | outItem:nil 390 | outRule:nil]; 391 | if (pageInvocation) 392 | { 393 | return YES; 394 | } 395 | 396 | NSInvocation *actionInvocation = 397 | [self.actionInvocationCenter invocationWithKey:key.lowercaseString 398 | data:data 399 | outItem:nil 400 | outRule:nil]; 401 | if (actionInvocation) 402 | { 403 | return YES; 404 | } 405 | else 406 | { 407 | return NO; 408 | } 409 | } 410 | 411 | - (BOOL)routerKey:(NSString *)key 412 | data:(NSDictionary *)data 413 | sender:(UIResponder *)sender 414 | pageBlock:(void (^)(__kindof UIViewController *))pageBlock 415 | callbackBlock:(void (^)(NSString *, NSString *, NSString *, BOOL))callbackBlock 416 | canNotRouterBlock:(void (^)(void))canNotRouterBlock 417 | { 418 | NSInvocation *invocation = [self.pageInvocationCenter invocationWithKey:key.lowercaseString 419 | data:data 420 | outItem:nil 421 | outRule:nil]; 422 | if (invocation) 423 | { 424 | [invocation invoke]; 425 | __unsafe_unretained UIViewController *unsafeVC = nil; 426 | [invocation getReturnValue:&unsafeVC]; 427 | UIViewController *ret = unsafeVC; 428 | if (pageBlock) 429 | { 430 | pageBlock(ret); 431 | } 432 | return YES; 433 | } 434 | 435 | LJInvocationCenterItem *outItem = nil; 436 | LJInvocationCenterItemRule *outRule = nil; 437 | 438 | NSMutableDictionary *actionData = [[NSMutableDictionary alloc] initWithDictionary:data]; 439 | actionData[@"sender"] = sender; 440 | invocation = [self.actionInvocationCenter invocationWithKey:key.lowercaseString 441 | data:actionData 442 | outItem:&outItem 443 | outRule:&outRule]; 444 | 445 | if (invocation) 446 | { 447 | __block BOOL hasCallbackBlock = NO; 448 | [outRule.paramas enumerateObjectsUsingBlock:^(LJInvocationCenterItemParam * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 449 | 450 | NSString *senderClass = NSStringFromClass([LJRouterSenderContext class]); 451 | 452 | if([obj.typeName hasPrefix:senderClass] 453 | && [obj.name.lowercaseString isEqualToString:@"sender"]) 454 | { 455 | __unsafe_unretained id originSender = nil; 456 | [invocation getArgument:&originSender atIndex:idx+2]; 457 | LJRouterSenderContext *senderContext = [[LJRouterSenderContext alloc] initWithSender:originSender]; 458 | [invocation setArgument:&senderContext atIndex:idx+2]; 459 | [invocation retainArguments]; 460 | } 461 | else if ([obj.typeName isEqualToString:LJRouterCallbackBlockName]) 462 | { 463 | hasCallbackBlock = YES; 464 | __unsafe_unretained id unsafe_data = nil; 465 | [invocation getArgument:&unsafe_data atIndex:idx+2]; 466 | id data = unsafe_data; 467 | 468 | void (^_callbackBlock)(NSString *,NSString *,NSString *,BOOL) = [callbackBlock copy]; 469 | 470 | void(^block)(NSString*,BOOL) = ^(NSString *blockData,BOOL complete) { 471 | if (_callbackBlock) 472 | { 473 | _callbackBlock(obj.name,data,blockData,complete); 474 | } 475 | }; 476 | block = [block copy]; 477 | [invocation setArgument:&block atIndex:idx+2]; 478 | [invocation retainArguments]; 479 | } 480 | }]; 481 | [invocation invoke]; 482 | 483 | 484 | if (!hasCallbackBlock && callbackBlock) 485 | { 486 | callbackBlock(nil,nil,nil,YES); 487 | } 488 | return YES; 489 | } 490 | 491 | if (canNotRouterBlock) 492 | { 493 | canNotRouterBlock(); 494 | } 495 | return NO; 496 | } 497 | 498 | - (LJInvocationCenterItem*)invocationItemForKey:(NSString*)key 499 | { 500 | LJInvocationCenterItem *item = [self.pageInvocationCenter getInvocationCenterItemByKey:key.lowercaseString]; 501 | if (item) 502 | { 503 | return item; 504 | } 505 | else 506 | { 507 | return [self.actionInvocationCenter getInvocationCenterItemByKey:key.lowercaseString]; 508 | } 509 | } 510 | 511 | - (void)openViewController:(UIViewController *)vc withSender:(id)sender 512 | { 513 | if (!vc) 514 | { 515 | return; 516 | } 517 | #pragma clang diagnostic push 518 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" 519 | #pragma clang diagnostic ignored "-Wundeclared-selector" 520 | if (self.openControllerBlock) 521 | { 522 | self.openControllerBlock(vc,sender); 523 | } 524 | 525 | else if (self.openControllerWithContextBlock) 526 | { 527 | self.openControllerWithContextBlock(vc, [[LJRouterSenderContext alloc] initWithSender:sender]); 528 | } 529 | else if ([vc respondsToSelector:@selector(LJNavigationOpenedByViewController:)]) 530 | { 531 | LJRouterSenderContext *senderContext = [[LJRouterSenderContext alloc] initWithSender:sender]; 532 | if (senderContext.contextViewController) 533 | { 534 | [vc performSelector:@selector(LJNavigationOpenedByViewController:) 535 | withObject: senderContext.contextViewController]; 536 | } 537 | else 538 | { 539 | [UIViewController performSelector:@selector(LJNavigationOpenViewController:) withObject:vc]; 540 | } 541 | } 542 | #pragma clang diagnostic pop 543 | else 544 | { 545 | NSLog(@"请配置 LJRouter 的 openControllerBlock 属性进行页面打开"); 546 | } 547 | } 548 | 549 | @end 550 | 551 | @implementation LJRouter(config) 552 | 553 | - (void)setCheckPolicy:(LJRouterCheckPolicy)checkPolicy 554 | { 555 | _checkPolicy = checkPolicy; 556 | } 557 | 558 | - (LJRouterCheckPolicy)checkPolicy 559 | { 560 | return _checkPolicy; 561 | } 562 | 563 | - (void)setCheckPolicyModules:(NSArray *)checkPolicyModules 564 | { 565 | _checkPolicyModules = checkPolicyModules; 566 | } 567 | 568 | - (NSArray*)checkPolicyModules 569 | { 570 | return _checkPolicyModules; 571 | } 572 | 573 | - (void)setOpenControllerBlock:(void (^)(UIViewController *, id))openControllerBlock 574 | { 575 | _openControllerBlock = [openControllerBlock copy]; 576 | } 577 | 578 | - (void (^)(UIViewController *, id))openControllerBlock 579 | { 580 | return _openControllerBlock; 581 | } 582 | 583 | - (void)setOpenControllerWithContextBlock:(void (^)(UIViewController *, LJRouterSenderContext *))openControllerWithContextBlock 584 | { 585 | _openControllerWithSenderBlock = openControllerWithContextBlock; 586 | } 587 | 588 | - (void(^)(UIViewController*,LJRouterSenderContext*))openControllerWithContextBlock 589 | { 590 | return _openControllerWithSenderBlock; 591 | } 592 | 593 | @end 594 | 595 | Class LJRouterGetClassForKey(NSString* key) 596 | { 597 | LJRouter *router = [LJRouter sharedInstance]; 598 | Class clazz = [router.pageInvocationCenter getInvocationCenterItemByKey:key.lowercaseString].target; 599 | if (clazz) 600 | { 601 | return clazz; 602 | } 603 | return [router.actionInvocationCenter getInvocationCenterItemByKey:key.lowercaseString].target; 604 | } 605 | 606 | NSInvocation* LJRouterGetInvocation(struct LJRouterInvocationStruct* invocations,uint32_t length) 607 | { 608 | LJRouterConvertManager *manager = [LJRouter sharedInstance].convertManager; 609 | NSMutableDictionary *data = nil; 610 | for (uint32_t i = 0 ; i < length ; i ++) 611 | { 612 | struct LJRouterInvocationStruct* invocation = invocations + i; 613 | LJInvocationCenterItemParam *param = [[LJInvocationCenterItemParam alloc] initWithName:invocation->name 614 | typeName:invocation->typeName 615 | typeEncoding:[NSString stringWithUTF8String:invocation->typeEncoding] 616 | isRequire:NO 617 | info:nil]; 618 | id jsonValue = [manager jsonValueWithInvokeValue:invocation->value param:param]; 619 | if (!jsonValue) 620 | { 621 | return nil; 622 | } 623 | if (!data) 624 | { 625 | data = [[NSMutableDictionary alloc] init]; 626 | } 627 | data[invocation->name] = jsonValue; 628 | } 629 | 630 | return nil; 631 | } 632 | -------------------------------------------------------------------------------- /LJRouter/Core/LJRouterConvertManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // LJRouterConvertManager.h 3 | // LJRouter 4 | // 5 | // Created by fover0 on 2017/11/28. 6 | // 7 | 8 | #import 9 | 10 | @class LJInvocationCenterItemParam; 11 | 12 | // 类型转化结果 13 | @interface LJRouterConvertInvokeValue : NSObject 14 | 15 | @property (nonatomic, readonly) void* result; 16 | 17 | + (instancetype)valueWithCType:(void*)result freeWhenDone:(BOOL)free; 18 | + (instancetype)valueWithRetainObj:(id)result; 19 | + (instancetype)valueError; 20 | 21 | @end 22 | 23 | 24 | @interface LJRouterConvertManager : NSObject 25 | 26 | - (LJRouterConvertInvokeValue*)invokeValueWithJson:(id)jsonValue param:(LJInvocationCenterItemParam*)param; 27 | - (id)jsonValueWithInvokeValue:(void*)jsonValue param:(LJInvocationCenterItemParam*)param; 28 | 29 | - (void)addCovertInvokeValueBlock:(LJRouterConvertInvokeValue*(^)(LJRouterConvertManager *manager, 30 | id value, 31 | LJInvocationCenterItemParam *targetParam))invokeValue; 32 | 33 | 34 | - (void)addConvertJsonValueBlock:(id(^)(LJRouterConvertManager *manager, 35 | void* value, 36 | LJInvocationCenterItemParam *valueParam))jsonValueBlock; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /LJRouter/Core/LJRouterConvertManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // LJRouterConvertManager.m 3 | // LJRouter 4 | // 5 | // Created by fover0 on 2017/11/28. 6 | // 7 | 8 | #import "LJRouterConvertManager.h" 9 | #import "LJInvocationCenter.h" 10 | #import "LJRouter.h" 11 | 12 | @interface LJRouterConvertInvokeValue() 13 | { 14 | @public 15 | __strong id _resultObj; 16 | void* _resultPointer; 17 | BOOL _freeWhenDone; 18 | } 19 | 20 | @end 21 | 22 | @implementation LJRouterConvertInvokeValue 23 | 24 | + (instancetype)valueWithRetainObj:(id)result 25 | { 26 | LJRouterConvertInvokeValue *ret = [[self alloc] init]; 27 | ret->_resultObj = result; 28 | return ret; 29 | } 30 | 31 | + (instancetype)valueWithCType:(void *)result freeWhenDone:(BOOL)free 32 | { 33 | LJRouterConvertInvokeValue *ret = [[self alloc] init]; 34 | ret->_resultPointer = result; 35 | ret->_freeWhenDone = free; 36 | return ret; 37 | } 38 | 39 | - (void*)result 40 | { 41 | if (_resultObj) 42 | { 43 | return &_resultObj; 44 | } 45 | else 46 | { 47 | return _resultPointer; 48 | } 49 | } 50 | 51 | + (instancetype)valueError 52 | { 53 | static id error = nil; 54 | static dispatch_once_t onceToken; 55 | dispatch_once(&onceToken, ^{ 56 | error = [[self alloc] init]; 57 | }); 58 | return error; 59 | } 60 | 61 | - (void)dealloc 62 | { 63 | if (self->_freeWhenDone) 64 | { 65 | free(self->_resultPointer); 66 | self->_resultPointer = NULL; 67 | } 68 | } 69 | 70 | @end 71 | 72 | @interface LJRouterConvertManager() 73 | @property (nonatomic, retain) NSMutableArray *invokeValueBlocks; 74 | @property (nonatomic, retain) NSMutableArray *jsonValueBlocks; 75 | @end 76 | 77 | @implementation LJRouterConvertManager 78 | 79 | #define ALL_NUMBER_TYPE(CONVERT_NUMBER) \ 80 | CONVERT_NUMBER(signed char ,_C_CHR , charValue) \ 81 | CONVERT_NUMBER(unsigned char ,_C_UCHR , unsignedCharValue) \ 82 | CONVERT_NUMBER(signed short ,_C_SHT , shortValue) \ 83 | CONVERT_NUMBER(unsigned short ,_C_USHT , unsignedShortValue) \ 84 | CONVERT_NUMBER(signed int ,_C_INT , intValue) \ 85 | CONVERT_NUMBER(unsigned int ,_C_UINT , unsignedIntValue) \ 86 | CONVERT_NUMBER(signed long ,_C_LNG , longValue) \ 87 | CONVERT_NUMBER(unsigned long ,_C_ULNG , unsignedLongValue) \ 88 | CONVERT_NUMBER(signed long long ,_C_LNG_LNG , longLongValue) \ 89 | CONVERT_NUMBER(bool ,_C_BOOL , boolValue) \ 90 | CONVERT_NUMBER(unsigned long long ,_C_ULNG_LNG, unsignedLongLongValue) \ 91 | CONVERT_NUMBER(float ,_C_FLT , floatValue) \ 92 | CONVERT_NUMBER(double ,_C_DBL , doubleValue) \ 93 | 94 | - (void)regNumberConvert 95 | { 96 | [self addCovertInvokeValueBlock:^LJRouterConvertInvokeValue *(LJRouterConvertManager *manager, 97 | id value, 98 | LJInvocationCenterItemParam *targetParam) { 99 | NSNumber*(^getNumber)(id numberObj) = ^NSNumber*(id numberObj){ 100 | if ([numberObj isKindOfClass:[NSString class]]) 101 | { 102 | NSNumberFormatter *f = [[NSNumberFormatter alloc] init]; 103 | return [f numberFromString:numberObj]; 104 | } 105 | else if ([numberObj isKindOfClass:[NSNumber class]]) 106 | { 107 | return numberObj; 108 | } 109 | else 110 | { 111 | return @0; 112 | } 113 | }; 114 | 115 | const char* type = targetParam.typeEncoding.UTF8String; 116 | switch (type[0]) { 117 | // 处理数字 118 | #define CONVERT_NUMBER(TYPE,TYPENAME,METHODNAME) \ 119 | case TYPENAME: \ 120 | { \ 121 | TYPE c = [getNumber(value) METHODNAME]; \ 122 | TYPE *result = (void*)malloc(sizeof(TYPE)); \ 123 | *result = c; \ 124 | return \ 125 | [LJRouterConvertInvokeValue valueWithCType:result freeWhenDone:YES]; \ 126 | } \ 127 | 128 | ALL_NUMBER_TYPE(CONVERT_NUMBER) 129 | #undef CONVERT_NUMBER 130 | default: 131 | return nil; 132 | } 133 | }]; 134 | 135 | [self addConvertJsonValueBlock:^id(LJRouterConvertManager *manager, 136 | void *value, 137 | LJInvocationCenterItemParam *valueParam) { 138 | const char* type = valueParam.typeEncoding.UTF8String; 139 | switch (type[0]) { 140 | #define CONVERT_NUMBER(TYPE,TYPENAME,METHODNAME) \ 141 | case TYPENAME: \ 142 | { \ 143 | TYPE *c = (TYPE*)value; \ 144 | return @(*c); \ 145 | } \ 146 | 147 | ALL_NUMBER_TYPE(CONVERT_NUMBER) 148 | #undef CONVERT_NUMBER 149 | default: 150 | return nil; 151 | } 152 | }]; 153 | } 154 | 155 | - (instancetype)init 156 | { 157 | self = [super init]; 158 | if (self) 159 | { 160 | self.invokeValueBlocks = [[NSMutableArray alloc] init]; 161 | self.jsonValueBlocks = [[NSMutableArray alloc] init]; 162 | 163 | [self regNumberConvert]; 164 | } 165 | return self; 166 | } 167 | 168 | - (void)addCovertInvokeValueBlock:(LJRouterConvertInvokeValue *(^)(LJRouterConvertManager *,id,LJInvocationCenterItemParam *))invokeValue 169 | { 170 | if (invokeValue) 171 | { 172 | [self.invokeValueBlocks addObject:invokeValue]; 173 | } 174 | } 175 | - (void)addConvertJsonValueBlock:(id (^)(LJRouterConvertManager *, void *, LJInvocationCenterItemParam *))jsonValueBlock 176 | { 177 | if (jsonValueBlock) 178 | { 179 | [self.jsonValueBlocks addObject:jsonValueBlock]; 180 | } 181 | } 182 | 183 | - (id)jsonValueWithInvokeValue:(void *)jsonValue param:(LJInvocationCenterItemParam *)param 184 | { 185 | for (id (^block)(LJRouterConvertManager *, void *, LJInvocationCenterItemParam *) in self.jsonValueBlocks) 186 | { 187 | id result = block(self,jsonValue,param); 188 | if (result) 189 | { 190 | return result; 191 | } 192 | } 193 | return nil; 194 | } 195 | 196 | - (LJRouterConvertInvokeValue*)invokeValueWithJson:(id)jsonValue param:(LJInvocationCenterItemParam*)param 197 | { 198 | for (LJRouterConvertInvokeValue *(^block)(LJRouterConvertManager *,id,LJInvocationCenterItemParam *) in self.invokeValueBlocks) 199 | { 200 | LJRouterConvertInvokeValue * value = block(self,jsonValue,param); 201 | if (value) 202 | { 203 | if (value == [LJRouterConvertInvokeValue valueError]) 204 | { 205 | return nil; 206 | } 207 | return value; 208 | } 209 | } 210 | return nil; 211 | } 212 | 213 | @end 214 | 215 | 216 | -------------------------------------------------------------------------------- /LJRouter/Core/LJUrlRouter.h: -------------------------------------------------------------------------------- 1 | // 2 | // LJUrlRouter.h 3 | // invocation 4 | // 5 | // Created by fover0 on 2017/6/6. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | #import "LJRouter.h" 10 | 11 | 12 | 13 | @interface LJRouter(LJUrlRouter) 14 | 15 | - (BOOL)canOpenUrlString:(NSString*)url; 16 | - (BOOL)routerUrlString:(NSString*)url 17 | sender:(UIResponder*)sender 18 | pageBlock:(void(^)(__kindof UIViewController* viewController))pageBlock 19 | callbackBlock:(void(^)(NSString* key,NSString *value,NSString* data,BOOL complete))callbackBlock 20 | canNotRouterBlock:(void(^)(void))canNotRouterBlock; 21 | @end 22 | 23 | @interface LJRouter(LJUrlRouterConfig) 24 | 25 | @property (nonatomic, copy) UIViewController *(^createWebviewBlock)(NSString* url); 26 | @property (nonatomic, copy) NSURL *(^urlProcessorBlock)(NSURL* url); 27 | 28 | @end 29 | 30 | @interface UIViewController(LJUrlRouter) 31 | 32 | + (void)LJSetWebViewControllerBlock:(__kindof UIViewController *(^)(NSString* url))block __deprecated; 33 | - (BOOL)LJOpenUrlString:(NSString*)url; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /LJRouter/Core/LJUrlRouter.m: -------------------------------------------------------------------------------- 1 | // 2 | // LJUrlRouter.m 3 | // invocation 4 | // 5 | // Created by fover0 on 2017/6/6. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | #import "LJUrlRouter.h" 10 | 11 | @implementation LJRouter(LJUrlRouterConfig) 12 | 13 | static char LJUrlRouter_urlProcessorBlock_Key; 14 | - (void)setUrlProcessorBlock:(NSURL *(^)(NSURL *))urlProcessorBlock 15 | { 16 | objc_setAssociatedObject(self, &LJUrlRouter_urlProcessorBlock_Key, [urlProcessorBlock copy], OBJC_ASSOCIATION_RETAIN); 17 | } 18 | - (NSURL *(^)(NSURL *))urlProcessorBlock 19 | { 20 | return objc_getAssociatedObject(self, &LJUrlRouter_urlProcessorBlock_Key); 21 | } 22 | 23 | static char LJUrlRouter_createWebviewBlock_Key; 24 | - (void)setCreateWebviewBlock:(UIViewController *(^)(NSString *))createWebviewBlock 25 | { 26 | objc_setAssociatedObject(self, &LJUrlRouter_createWebviewBlock_Key, [createWebviewBlock copy], OBJC_ASSOCIATION_RETAIN); 27 | } 28 | - (UIViewController *(^)(NSString *))createWebviewBlock 29 | { 30 | return objc_getAssociatedObject(self, &LJUrlRouter_createWebviewBlock_Key); 31 | } 32 | 33 | @end 34 | 35 | 36 | @implementation UIViewController(LJUrlRouter) 37 | 38 | + (void)LJSetWebViewControllerBlock:(__kindof UIViewController *(^)(NSString *))block 39 | { 40 | LJRouter.sharedInstance.createWebviewBlock = block; 41 | } 42 | 43 | 44 | - (BOOL)LJOpenUrlString:(NSString *)url 45 | { 46 | if (url.length == 0) 47 | { 48 | return NO; 49 | } 50 | 51 | BOOL canRout = 52 | [[LJRouter sharedInstance] routerUrlString:url 53 | sender:self 54 | pageBlock:^(__kindof UIViewController *viewController) { 55 | [[LJRouter sharedInstance] openViewController:viewController withSender:self]; 56 | } 57 | callbackBlock:nil 58 | canNotRouterBlock:nil]; 59 | if (!canRout) 60 | { 61 | UIViewController *(^webviewBlock)(NSString *) = [LJRouter sharedInstance].createWebviewBlock; 62 | 63 | UIViewController *webVC = webviewBlock ? webviewBlock(url) : nil; 64 | if (webVC) 65 | { 66 | canRout = YES; 67 | [[LJRouter sharedInstance] openViewController:webVC withSender:self]; 68 | } 69 | } 70 | return canRout; 71 | } 72 | 73 | @end 74 | 75 | 76 | 77 | static NSString *const uq_URLReservedChars = @"=,!$&'()*+;@?\r\n\"<>#\t :/"; 78 | static NSString *const kQuerySeparator = @"&"; 79 | static NSString *const kQueryDivider = @"="; 80 | static NSString *const kQueryBegin = @"?"; 81 | static NSString *const kFragmentBegin = @"#"; 82 | 83 | @implementation LJRouter(LJUrlRouter) 84 | 85 | - (NSDictionary*)uq_URLQueryDictionary:(NSString*)string { 86 | NSMutableDictionary *mute = @{}.mutableCopy; 87 | for (NSString *query in [string componentsSeparatedByString:kQuerySeparator]) { 88 | NSArray *components = [query componentsSeparatedByString:kQueryDivider]; 89 | if (components.count == 0) { 90 | continue; 91 | } 92 | NSString *key = [components[0] stringByRemovingPercentEncoding]; 93 | id value = nil; 94 | if (components.count == 1) { 95 | // key with no value 96 | value = [NSNull null]; 97 | } 98 | if (components.count == 2) { 99 | value = [components[1] stringByRemovingPercentEncoding]; 100 | // cover case where there is a separator, but no actual value 101 | value = [value length] ? value : [NSNull null]; 102 | } 103 | if (components.count > 2) { 104 | // invalid - ignore this pair. is this best, though? 105 | continue; 106 | } 107 | mute[key.lowercaseString] = value ?: [NSNull null]; 108 | } 109 | return mute.count ? mute.copy : nil; 110 | } 111 | 112 | - (void)decodeUrlString:(NSString*)urlString 113 | outkey:(NSString**)outKey 114 | outData:(NSDictionary**)outData 115 | { 116 | if (urlString.length == 0) 117 | { 118 | *outKey = nil; 119 | *outData = @{}; 120 | return; 121 | } 122 | 123 | NSURL * url = [NSURL URLWithString:urlString]; 124 | if (!url) 125 | { 126 | urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 127 | url = [NSURL URLWithString:urlString]; 128 | } 129 | 130 | NSURL* (^urlProcessor)(NSURL*) = [LJRouter sharedInstance].urlProcessorBlock; 131 | if (urlProcessor && url.absoluteString.length) 132 | { 133 | url = urlProcessor(url); 134 | } 135 | 136 | if (url.absoluteString.length == 0 || url.host.length == 0) 137 | { 138 | *outKey = nil; 139 | *outData = @{}; 140 | return; 141 | } 142 | 143 | NSMutableString *key = [[NSMutableString alloc] initWithString:url.host]; 144 | for (NSString *path in url.pathComponents) 145 | { 146 | if (![path isEqualToString:@"/"]) 147 | { 148 | [key appendFormat:@"_%@",path]; 149 | } 150 | } 151 | NSDictionary *data = [self uq_URLQueryDictionary:url.query]; 152 | 153 | *outKey = key; 154 | *outData = data; 155 | } 156 | 157 | - (BOOL)canOpenUrlString:(NSString *)url 158 | { 159 | NSString *key = nil; 160 | NSDictionary *data = nil; 161 | [self decodeUrlString:url outkey:&key outData:&data]; 162 | return [self canRouterKey:key data:data]; 163 | } 164 | 165 | - (BOOL)routerUrlString:(NSString *)url 166 | sender:(UIResponder *)sender 167 | pageBlock:(void (^)(__kindof UIViewController *))pageBlock 168 | callbackBlock:(void (^)(NSString *, NSString *, NSString *, BOOL))callbackBlock 169 | canNotRouterBlock:(void (^)(void))canNotRouterBlock 170 | { 171 | NSString *key = nil; 172 | NSDictionary *data = nil; 173 | [self decodeUrlString:url outkey:&key outData:&data]; 174 | return [self routerKey:key 175 | data:data 176 | sender:sender 177 | pageBlock:pageBlock 178 | callbackBlock:callbackBlock 179 | canNotRouterBlock:canNotRouterBlock]; 180 | } 181 | 182 | @end 183 | 184 | 185 | -------------------------------------------------------------------------------- /LJRouter/ExportDocument/LJRouterExportDevDocument.m: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // LJRouterExportDevDocument.m 4 | // 5 | // Created by fover0 on 2017/5/31. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | #import 10 | #import 11 | 12 | #import "../ExportTool/LJRouterExportModule.h" 13 | 14 | NSString *getHeaderFilePathWithFilePath(NSString *curPath, NSString* filePath,BOOL isPage) 15 | { 16 | NSArray *paths = [filePath pathComponents]; 17 | for (NSInteger i = paths.count - 2; i >=0 ; i--) 18 | { 19 | if ([paths[i] hasSuffix:@"Component"] || [paths[i] hasSuffix:@"Module"] ) 20 | { 21 | return [curPath stringByAppendingFormat:@"/%@Header.h",paths[i]]; 22 | } 23 | } 24 | return nil; 25 | } 26 | 27 | void writeStringToFile(NSString* string,NSString *file,NSMutableDictionary *opendFiles) 28 | { 29 | if (!file.length) 30 | { 31 | return; 32 | } 33 | 34 | NSNumber *fileIdNumber = opendFiles[file]; 35 | if (!fileIdNumber) 36 | { 37 | int fileid = open(file.UTF8String,O_RDWR | O_CREAT | O_TRUNC, S_IRWXU|S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH); 38 | fileIdNumber = [NSNumber numberWithInt:fileid]; 39 | opendFiles[file] = fileIdNumber; 40 | } 41 | write(fileIdNumber.intValue, string.UTF8String, strlen(string.UTF8String)); 42 | } 43 | void closeAllFile(NSMutableDictionary* opendFiles) 44 | { 45 | [opendFiles enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, NSNumber *obj, BOOL * _Nonnull stop) { 46 | close(obj.intValue); 47 | }]; 48 | } 49 | 50 | static void printHeaders(NSMutableDictionary *opendFileId, 51 | NSString *outputPath, 52 | NSArray *items) { 53 | for (NSInteger printAction = 0 ; printAction < 2 ; printAction++) 54 | { 55 | for (LJRegistExportItem *item in items) 56 | { 57 | // 先输出page再输出action 58 | if (printAction == 0 && item.isAction) 59 | { 60 | continue; 61 | } 62 | if (printAction == 1 && !item.isAction) 63 | { 64 | continue; 65 | } 66 | NSString *path = getHeaderFilePathWithFilePath(outputPath,item.filepath, YES); 67 | 68 | NSMutableString *string = [[NSMutableString alloc] init]; 69 | 70 | NSString *processedName = [item.keyDescription stringByReplacingOccurrencesOfString:@"//" withString:@"\n//"]; 71 | 72 | [string appendFormat:@"// %@ : %@ \n",item.isAction ? @"action":@"页面",processedName]; 73 | 74 | [string appendFormat:@"%@(%@",item.isAction ? @"LJRouterUseAction":@"LJRouterUsePage", 75 | item.key]; 76 | 77 | if (item.isAction) 78 | { 79 | [string appendFormat:@", %@",item.returnTypeName]; 80 | } 81 | 82 | for (LJRegistExportItemParam *param in item.params) 83 | { 84 | [string appendFormat:@", (%@)%@",param.typeName,param.name]; 85 | } 86 | [string appendString:@");\n"]; 87 | 88 | writeStringToFile(string, path, opendFileId); 89 | } 90 | } 91 | } 92 | 93 | static void printJson(NSArray*items,NSString *exportPath) 94 | { 95 | 96 | 97 | NSMutableArray *pageArray = [[NSMutableArray alloc] init]; 98 | NSMutableArray *actionArray = [[NSMutableArray alloc] init]; 99 | [items enumerateObjectsUsingBlock:^(LJRegistExportItem * _Nonnull obj, 100 | NSUInteger idx, 101 | BOOL * _Nonnull stop) { 102 | NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; 103 | if (obj.isAction) 104 | { 105 | [actionArray addObject:dict]; 106 | } 107 | else 108 | { 109 | [pageArray addObject:dict]; 110 | } 111 | 112 | dict[@"key"] = obj.key; 113 | dict[@"actionDesc"] = obj.keyDescription; 114 | NSMutableArray *params = [[NSMutableArray alloc] init]; 115 | dict[@"parameters"] = params; 116 | 117 | [obj.params enumerateObjectsUsingBlock:^(LJRegistExportItemParam * _Nonnull param, NSUInteger idx, BOOL * _Nonnull stop) { 118 | NSMutableDictionary *paramDict = [[NSMutableDictionary alloc] init]; 119 | [params addObject:paramDict]; 120 | paramDict[@"name"] = param.name; 121 | }]; 122 | }]; 123 | 124 | NSError *parseError = nil; 125 | NSData *pageData = [NSJSONSerialization dataWithJSONObject:pageArray 126 | options:NSJSONWritingPrettyPrinted 127 | error:&parseError]; 128 | [pageData writeToFile:[exportPath stringByAppendingString:@"/page.json"] atomically:YES]; 129 | 130 | NSData *actionData = [NSJSONSerialization dataWithJSONObject:actionArray 131 | options:NSJSONWritingPrettyPrinted 132 | error:&parseError]; 133 | [actionData writeToFile:[exportPath stringByAppendingString:@"/action.json"] atomically:YES]; 134 | } 135 | 136 | int main(int argc, const char **argv) 137 | { 138 | char* buildDir = getenv("TARGET_BUILD_DIR"); 139 | char* execPath = getenv("EXECUTABLE_PATH"); 140 | char* projectDir = getenv("PROJECT_DIR"); 141 | 142 | if (!buildDir || !execPath || !projectDir || argc < 2) 143 | { 144 | NSLog(@"没有参数"); 145 | return 0; 146 | } 147 | BOOL exportJson = NO; 148 | const char *outputDir = "outputHeaders"; 149 | for (int i = 1; i < argc; i++) 150 | { 151 | if (strcmp(argv[i],"--json") == 0) 152 | { 153 | exportJson = YES; 154 | } 155 | else 156 | { 157 | outputDir = argv[i]; 158 | } 159 | } 160 | 161 | 162 | NSString *path = [[NSString alloc] initWithFormat:@"%s/%s",buildDir,execPath]; 163 | NSString *outputPath = [[NSString alloc] initWithFormat:@"%s/%s",projectDir,outputDir]; 164 | 165 | NSLog(@"二进制文件为 %@",path); 166 | NSLog(@"输出目录为 %@",outputPath); 167 | 168 | mkdir(outputPath.UTF8String,ALLPERMS); 169 | 170 | NSArray *allItems = loadAllRegItemByPath(path); 171 | 172 | NSMutableDictionary *opendFileId = [[NSMutableDictionary alloc] init]; 173 | 174 | // 写页面 175 | printHeaders(opendFileId, outputPath, allItems); 176 | 177 | if (exportJson == YES) 178 | { 179 | printJson(allItems,outputPath); 180 | } 181 | 182 | closeAllFile(opendFileId); 183 | } 184 | 185 | 186 | -------------------------------------------------------------------------------- /LJRouter/ExportTool/LJRouterExportModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // LJRouterExportModule.h 4 | // 5 | // Created by fover0 on 2017/5/31. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | #import 10 | 11 | @interface LJRegistExportItemParam : NSObject 12 | 13 | @property (nonatomic, readonly) BOOL isRequire; 14 | @property (nonatomic, readonly) NSString *name; 15 | @property (nonatomic, readonly) NSString *typeName; 16 | @property (nonatomic, readonly) NSString *typeEncoding; 17 | 18 | @end 19 | 20 | @interface LJRegistExportItem : NSObject 21 | 22 | @property (nonatomic, readonly) BOOL isAction; 23 | @property (nonatomic, readonly) NSString *className; 24 | @property (nonatomic, readonly) NSString *categoryName; 25 | @property (nonatomic, readonly) NSString *returnTypeName; 26 | @property (nonatomic, readonly) NSString *returnTypeEncoding; 27 | @property (nonatomic, readonly) NSString *key; 28 | @property (nonatomic, readonly) NSString *keyDescription; 29 | @property (nonatomic, readonly) NSArray *params; 30 | @property (nonatomic, readonly) NSString *selName; 31 | @property (nonatomic, readonly) NSString *filepath; 32 | 33 | @end 34 | 35 | NSArray* loadAllRegItemByPath(NSString* path); 36 | 37 | -------------------------------------------------------------------------------- /LJRouter/ExportTool/LJRouterExportModule.m: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // LJRouterExportModule.m 4 | // 5 | // Created by fover0 on 2017/5/31. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #import 13 | #import 14 | #import 15 | #import 16 | #import "LJRouterExportModule.h" 17 | 18 | #import "../Core/LJRouterPrivate.h" 19 | 20 | @interface LJRegistExportItemParam () 21 | 22 | @property (nonatomic, assign) BOOL isRequire; 23 | @property (nonatomic, copy) NSString *name; 24 | @property (nonatomic, copy) NSString *typeName; 25 | @property (nonatomic, copy) NSString *typeEncoding; 26 | @property (nonatomic, copy) NSString *paramDescription; 27 | 28 | @end 29 | 30 | @implementation LJRegistExportItemParam 31 | 32 | - (NSString*)description 33 | { 34 | return [NSString stringWithFormat:@"name:%@\n" 35 | "type:%@\n" 36 | "require:%@", 37 | self.name, 38 | self.typeName, 39 | self.isRequire?@"必须":@"可选"]; 40 | } 41 | @end 42 | 43 | @interface LJRegistExportItem () 44 | @property (nonatomic, assign) BOOL isAction; 45 | @property (nonatomic, copy) NSString *className; 46 | @property (nonatomic, copy) NSString *categoryName; 47 | @property (nonatomic, copy) NSString *returnTypeName; 48 | @property (nonatomic, copy) NSString *returnTypeEncoding; 49 | @property (nonatomic, copy) NSString *returnAttrDesp; 50 | @property (nonatomic, copy) NSString *key; 51 | @property (nonatomic, copy) NSString *keyDescription; 52 | @property (nonatomic, retain) NSArray *params; 53 | @property (nonatomic, copy) NSString *selName; 54 | @property (nonatomic, copy) NSString *filepath; 55 | 56 | @end 57 | 58 | @implementation LJRegistExportItem 59 | - (NSString*)description 60 | { 61 | return [NSString stringWithFormat:@"className:%@\n" 62 | "key:%@\n" 63 | "description:%@", 64 | self.className, 65 | self.key, 66 | self.keyDescription]; 67 | } 68 | @end 69 | 70 | // 模拟一个假的结构体 引用C语言的结构体 内存布局是固定的 71 | struct stringstruct { 72 | void* isa; 73 | uint64_t encoding; 74 | char* cstring; 75 | uint64_t len; 76 | }; 77 | 78 | static void* getPointerFromAddr(void*data , void* offset) 79 | { 80 | uint8_t *pointer = (uint8_t*)((uint8_t*)data + (uint32_t)offset); 81 | return pointer; 82 | } 83 | 84 | static NSString* getStringFromAddr(void *data, __unsafe_unretained NSString *offset) 85 | { 86 | struct stringstruct *strStruct = getPointerFromAddr(data, (__bridge void*)offset); 87 | char* strPointer = getPointerFromAddr(data, strStruct->cstring); 88 | NSString *string = nil; 89 | if (strStruct->encoding == 0x000007D0) { 90 | string = [[NSString alloc] initWithBytes:strPointer length:strStruct->len * 2 encoding:NSUTF16LittleEndianStringEncoding]; 91 | } 92 | else 93 | { 94 | string = [[NSString alloc] initWithBytes:strPointer length:strStruct->len encoding:NSUTF8StringEncoding]; 95 | } 96 | return string; 97 | } 98 | 99 | static NSArray* readLJRouterStruct(void *data,struct section_64 *section) 100 | { 101 | uint64_t routerSize = section->size/sizeof(struct LJRouterRegister); 102 | struct LJRouterRegister *Res = (struct LJRouterRegister *)((uint8_t*)data + section->offset); 103 | NSMutableArray *allItems = [[NSMutableArray alloc] init]; 104 | for (int k = 0; k < routerSize; k++) 105 | { 106 | LJRegistExportItem *item = [[LJRegistExportItem alloc] init]; 107 | [allItems addObject:item]; 108 | item.isAction = Res[k].isAction; 109 | 110 | NSString *functionName = [NSString stringWithUTF8String:getPointerFromAddr(data, Res[k].objcFunctionName)]; 111 | NSRange range = [functionName rangeOfString:@" "]; 112 | functionName = [functionName substringWithRange:NSMakeRange(2, range.location - 2)]; 113 | NSString *className = functionName; 114 | NSString *categroyName = nil; 115 | range = [functionName rangeOfString:@"("]; 116 | if (range.length != 0) 117 | { 118 | className = [functionName substringToIndex:range.location]; 119 | categroyName = [functionName substringWithRange:NSMakeRange(range.location + 1, functionName.length - 2 - className.length)]; 120 | } 121 | item.className = className; 122 | item.categoryName = categroyName; 123 | 124 | item.returnTypeName = getStringFromAddr(data, Res[k].returnTypeName); 125 | item.returnTypeEncoding = [NSString stringWithUTF8String: getPointerFromAddr(data, Res[k].returnTypeEncoding)]; 126 | 127 | item.key = getStringFromAddr(data, Res[k].key); 128 | item.keyDescription = getStringFromAddr(data, Res[k].keyDescription); 129 | item.selName = getStringFromAddr(data,Res[k].selName); 130 | item.filepath = [[NSString alloc] initWithUTF8String:getPointerFromAddr(data, Res[k].filePath)]; 131 | 132 | NSMutableArray *paramsArray = nil; 133 | if (Res[k].paramscount) 134 | { 135 | paramsArray = [[NSMutableArray alloc] init]; 136 | } 137 | item.params = paramsArray; 138 | 139 | // params 140 | uint32_t paramscount = Res[k].paramscount; 141 | struct LJRouterRegisterParam *params = getPointerFromAddr(data,Res[k].params); 142 | for(int l = 0; l < paramscount; l++) 143 | { 144 | LJRegistExportItemParam *p = [[LJRegistExportItemParam alloc] init]; 145 | p.name = getStringFromAddr(data, params[l].name); 146 | p.typeName = getStringFromAddr(data, params[l].typeName); 147 | const char *typeEncoding = getPointerFromAddr(data, params[l].typeEncoding); 148 | p.typeEncoding = [NSString stringWithUTF8String:typeEncoding] ; 149 | p.isRequire = params[l].isRequire; 150 | [paramsArray addObject:p]; 151 | } 152 | } 153 | return allItems; 154 | } 155 | 156 | NSArray* loadAllRegItemByPath(NSString* path) 157 | { 158 | // 全局 159 | NSArray *allItems = nil; 160 | 161 | // 开始工作 162 | if (path.length == 0 || ![[NSFileManager defaultManager] fileExistsAtPath:path]) { 163 | return nil; 164 | } 165 | NSString *file = path; 166 | 167 | int fileid = open(file.UTF8String, 0, O_RDONLY); 168 | off_t len = lseek(fileid, 0, SEEK_END); 169 | 170 | void *data = mmap(NULL, 171 | len, 172 | PROT_READ, 173 | MAP_PRIVATE, 174 | fileid, 175 | 0); 176 | // 最最外层是fat 177 | // 最外层header 178 | struct mach_header_64 header = *((struct mach_header_64*)data); 179 | // NSLog(@"header magic Number is %x",header.magic); 180 | if ((MH_MAGIC_64 != header.magic )&& (MH_CIGAM_64 != header.magic)) { // 忽略32位 181 | close(fileid); 182 | return nil; 183 | } 184 | // 第二层是 command // 强转为uint8是因为不强转 指针转换按照 操作系统长度操作 64位下就是8字节 185 | struct load_command *cmds = (struct load_command *)((uint8_t*)data + sizeof(struct mach_header_64)); 186 | 187 | for (uint32_t i = 0 ; i < header.ncmds ; i++,cmds = (struct load_command *)((uint8_t*)cmds + cmds->cmdsize)) { 188 | // 如果是 segment_command_64(一般只关注2种 __DATA,__TEXT) 189 | // 则有第三层 section 190 | if (cmds->cmd != LC_SEGMENT_64) { 191 | continue; 192 | } 193 | struct segment_command_64 *segmentCmd = (struct segment_command_64 *)cmds; 194 | char *name = segmentCmd->segname; 195 | if (0 != strcmp(name, "__DATA")) { 196 | continue; 197 | } 198 | struct section_64 *secions = (struct section_64 *)((uint8_t*)cmds + sizeof(struct segment_command_64)); 199 | 200 | for (uint32_t j = 0 ; j < segmentCmd->nsects ; j++, secions += 1) 201 | { 202 | if (0 == strcmp(secions->sectname, "__LJRouter")) 203 | { 204 | allItems = readLJRouterStruct(data, secions); 205 | } 206 | else 207 | { 208 | continue; 209 | } 210 | } 211 | } 212 | close(fileid); 213 | return allItems; 214 | } 215 | 216 | 217 | 218 | -------------------------------------------------------------------------------- /LJRouter/Navigation/UIViewController+LJNavigation.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+LJNavigation.h 3 | // invocation 4 | // 5 | // Created by fover0 on 2017/6/20. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, LJNavigationType) 12 | { 13 | LJNavigationTypePush = 0, 14 | LJNavigationTypePresent = 1, 15 | LJNavigationTypePresentWithNavigation = 2, 16 | 17 | LJNavigationTypeNoAnimation = 1 << 16, 18 | }; 19 | 20 | // 对于导航的一些配置 21 | @interface LJNavigationConfig : NSObject 22 | 23 | @property (nonatomic, retain) Class navigationControllerClass; 24 | @property (nonatomic, copy) __kindof UIViewController*(^findTopViewControllerBlock)(void); 25 | 26 | - (void)setup; 27 | 28 | @end 29 | 30 | @interface UIViewController (LJNavigation) 31 | 32 | @property (nonatomic, assign) LJNavigationType ljNavigationType; 33 | 34 | // 自己被别的vc打开时调用 定制当前vc的显示方式 或者弹出登录框等操作 35 | - (void)LJNavigationOpenedByViewController:(__kindof UIViewController*)viewController; 36 | 37 | // 要打开别的vc时调用 38 | - (void)LJNavigationOpenViewController:(__kindof UIViewController*)nextViewController; 39 | 40 | // 当要打开一个vc时 没有当前vc时调用 41 | + (void)LJNavigationOpenViewController:(__kindof UIViewController*)nextViewController; 42 | 43 | - (void)closeSelf; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /LJRouter/Navigation/UIViewController+LJNavigation.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+LJNavigation.m 3 | // invocation 4 | // 5 | // Created by fover0 on 2017/6/20. 6 | // Copyright(c) 2017 Lianjia, Inc. All Rights Reserved 7 | // 8 | 9 | #import "UIViewController+LJNavigation.h" 10 | #import 11 | 12 | static LJNavigationConfig *usedConfig; 13 | @implementation LJNavigationConfig 14 | 15 | - (void)setup 16 | { 17 | usedConfig = self; 18 | } 19 | 20 | @end 21 | 22 | @implementation UIViewController (LJNavigation) 23 | 24 | static char navigationTypeKey; 25 | - (void)setLjNavigationType:(LJNavigationType)ljNavigationType 26 | { 27 | objc_setAssociatedObject(self, &navigationTypeKey, [NSNumber numberWithInteger:ljNavigationType], OBJC_ASSOCIATION_RETAIN_NONATOMIC); 28 | } 29 | 30 | - (LJNavigationType)ljNavigationType 31 | { 32 | return [objc_getAssociatedObject(self, &navigationTypeKey) integerValue]; 33 | } 34 | 35 | static char navigationCloseBlockKey; 36 | - (void)setLJNavigationCloseBlock:(void(^)(void))closeBlock 37 | { 38 | objc_setAssociatedObject(self, &navigationCloseBlockKey, [closeBlock copy], OBJC_ASSOCIATION_COPY); 39 | } 40 | 41 | - (void(^)(void))LJNavigationCloseBlock 42 | { 43 | return objc_getAssociatedObject(self, &navigationCloseBlockKey); 44 | } 45 | 46 | 47 | static BOOL tryPushOpen(UIViewController *fromVC,UIViewController *toVC,BOOL animated) 48 | { 49 | if (fromVC.navigationController) 50 | { 51 | [fromVC.navigationController pushViewController:toVC animated:animated]; 52 | [toVC setLJNavigationCloseBlock:^{ 53 | [fromVC.navigationController popViewControllerAnimated:animated]; 54 | }]; 55 | return YES; 56 | } 57 | else 58 | { 59 | return tryPresentWithNavigationOpen(fromVC, toVC,animated); 60 | } 61 | } 62 | 63 | static BOOL tryPresentOpen(UIViewController *fromVC,UIViewController *toVC,BOOL animated) 64 | { 65 | [fromVC presentViewController:toVC animated:animated completion:nil]; 66 | __weak UIViewController *wvc = toVC; 67 | [toVC setLJNavigationCloseBlock:^{ 68 | [wvc dismissViewControllerAnimated:animated completion:nil]; 69 | }]; 70 | return YES; 71 | } 72 | 73 | static BOOL tryPresentWithNavigationOpen(UIViewController *fromVC,UIViewController *toVC,BOOL animated) 74 | { 75 | Class navClass = Nil; 76 | if ([usedConfig.navigationControllerClass isSubclassOfClass:[UINavigationController class]]) 77 | { 78 | navClass = usedConfig.navigationControllerClass; 79 | } 80 | else 81 | { 82 | navClass = [UINavigationController class]; 83 | } 84 | 85 | UINavigationController *navVC = [[navClass alloc] initWithRootViewController:toVC]; 86 | navVC.modalPresentationStyle = toVC.modalPresentationStyle; 87 | [fromVC presentViewController:navVC animated:animated completion:nil]; 88 | 89 | __weak UINavigationController *weakNavVC = navVC; 90 | 91 | [toVC setLJNavigationCloseBlock:^{ 92 | UINavigationController *strongNavVC = weakNavVC; 93 | [strongNavVC dismissViewControllerAnimated:animated completion:nil]; 94 | }]; 95 | 96 | return YES; 97 | } 98 | 99 | // 自己被别的vc打开时调用 定制当前vc的显示方式 或者弹出登录框等操作 100 | - (void)LJNavigationOpenedByViewController:(__kindof UIViewController*)viewController 101 | { 102 | LJNavigationType type = self.ljNavigationType; 103 | BOOL animated = !(type & LJNavigationTypeNoAnimation); 104 | if (!animated) 105 | { 106 | type = type - LJNavigationTypeNoAnimation; 107 | } 108 | 109 | switch (type) { 110 | case LJNavigationTypePush : 111 | tryPushOpen(viewController,self,animated); 112 | break; 113 | case LJNavigationTypePresent : 114 | tryPresentOpen(viewController, self,animated); 115 | break; 116 | case LJNavigationTypePresentWithNavigation : 117 | tryPresentWithNavigationOpen(viewController, self,animated); 118 | break; 119 | default: 120 | // do nothing 121 | break; 122 | } 123 | } 124 | 125 | // 要打开别的vc时调用 126 | - (void)LJNavigationOpenViewController:(__kindof UIViewController*)nextViewController 127 | { 128 | [nextViewController LJNavigationOpenedByViewController:self]; 129 | } 130 | 131 | // 当要打开一个vc时 没有当前vc时调用 132 | + (void)LJNavigationOpenViewController:(__kindof UIViewController*)nextViewController 133 | { 134 | UIViewController *curVC = usedConfig.findTopViewControllerBlock ? usedConfig.findTopViewControllerBlock() : nil; 135 | if (!curVC) 136 | { 137 | id appdelegate = [UIApplication sharedApplication].delegate; 138 | UIWindow *window = nil; 139 | // 一般默认生成appdelegate的window属性 140 | if ([appdelegate respondsToSelector:@selector(window)]) 141 | { 142 | window = [appdelegate performSelector:@selector(window)]; 143 | } 144 | // 如果没有window属性 145 | else 146 | { 147 | if ([UIApplication sharedApplication].windows.count > 0) 148 | { 149 | window = [UIApplication sharedApplication].windows[0]; 150 | } 151 | } 152 | curVC = window.rootViewController; 153 | while (1) { 154 | if (curVC.presentingViewController && ![curVC.presentingViewController isKindOfClass:[UIAlertController class]]) 155 | { 156 | curVC = curVC.presentingViewController; 157 | } 158 | else if ([curVC isKindOfClass:[UINavigationController class]]) 159 | { 160 | UINavigationController *vc = (id)curVC; 161 | curVC = vc.topViewController; 162 | } 163 | else if ([curVC isKindOfClass:[UITabBarController class]]) 164 | { 165 | UITabBarController *vc = (id)curVC; 166 | curVC = vc.selectedViewController; 167 | } 168 | else 169 | { 170 | break; 171 | } 172 | } 173 | } 174 | if (curVC) 175 | { 176 | [curVC LJNavigationOpenViewController:nextViewController]; 177 | } 178 | else 179 | { 180 | [nextViewController LJNavigationOpenedByViewController:nil]; 181 | } 182 | } 183 | 184 | - (void)closeSelf 185 | { 186 | void(^closeBlock)(void) = [self LJNavigationCloseBlock]; 187 | if (closeBlock) 188 | { 189 | closeBlock(); 190 | } 191 | else 192 | { 193 | BOOL animated = !(self.ljNavigationType & LJNavigationTypeNoAnimation); 194 | if (self.navigationController) 195 | { 196 | if (self.navigationController.viewControllers.count == 1) 197 | { 198 | [self.navigationController dismissViewControllerAnimated:animated completion:nil]; 199 | } 200 | else 201 | { 202 | [self.navigationController popViewControllerAnimated:animated]; 203 | } 204 | } 205 | else if (self.presentedViewController) 206 | { 207 | [self dismissViewControllerAnimated:animated completion:nil]; 208 | } 209 | } 210 | } 211 | 212 | 213 | @end 214 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #LJRouter 2 | ## 0.Example 3 | Example中,请先编译LJRouterExportModule生成文档组件,再运行LJRouter-Example才可生成文档。 4 | 5 | ## 1.接入 6 | ### 1.1 拉取代码 7 | 推荐使用cocoapods进行接入, 8 | 在项目的Podfile中添加如下代码 9 | ```ruby 10 | pod 'LJRouter' 11 | ``` 12 | 然后执行 pod install/update 13 | ### 1.2 编译配置 14 | 在项目的BuildPhases的设置中,点击左上角加号,再点击New Run Script Phase.在新出现的Run Script添加如下代码。 15 | ```powershell 16 | ${PODS_ROOT}/LJRouter/build /LJAutogenComponentHeaders 17 | ``` 18 | LJAutogenComponentHeaders 可以修改为您需要的名字,后续自动生成的代码会导出到你的项目下该名字的目录中。 19 | 20 | **注意:文件夹只有以Module结尾时被认为是一个模块,该文件夹下的文件才可以生成头文件(递归)** 21 | ### 1.3 添加文件 22 | 进行过 1.1 和 1.2 步骤之后,编译您的代码,然后您会在项目的目录下发现 1.2 中的文件夹,在xcode的源码管理页面中,选择Add files to "xxxxx",然后选择Create folder references,去掉target选项,再选择 步骤1.2 的文件夹,点击Add.后续自动生成的头文件就会出现在该文件夹中了。 23 | `注意:请不要直接引用自动生成的头文件` 24 | 25 | ### 1.4 跳转页面配置 26 | 默认路由只处理分发消息,不处理跳转逻辑,如果搭配LJNavigation使用,请在AppDelegate中添加以下代码。 27 | ```objectivec 28 | [[LJRouter sharedInstance] setOpenControllerWithContextBlock:^(UIViewController *vc, LJRouterSenderContext *senderContext) { 29 | if (senderContext) 30 | { 31 | [senderContext.contextViewController LJNavigationOpenViewController:vc]; 32 | } 33 | else 34 | { 35 | [UIViewController LJNavigationOpenViewController:vc]; 36 | } 37 | }]; 38 | ``` 39 | ### 1.5 自定义类型配置(可选) 40 | LJRouter默认支持 数字与字符串的转换,如果您希望将一些其他类型的参数通过外部字符串调用,则需要主动注册一些解析函数,下面的例子是注册一个Json字符串转NSDictionary的例子 41 | ```objectivec 42 | [[LJRouter sharedInstance] addParamConvertTypeBlock:^LJInvocationCenterConvertResult *(id value, NSString *typeName, NSString *typeEncoding) { 43 | if ([typeEncoding isEqualToString:@"@"] 44 | && [typeName hasPrefix:NSStringFromClass([NSDictionary class])]) 45 | { 46 | NSData *stringData = [value dataUsingEncoding:NSUTF8StringEncoding]; 47 | id json = [NSJSONSerialization JSONObjectWithData:stringData options:0 error:nil]; 48 | if ([json isKindOfClass:[NSDictionary class]]) 49 | { 50 | return [LJInvocationCenterConvertResult resultWithRetainObj:json]; 51 | } 52 | } 53 | return nil; 54 | }]; 55 | ``` 56 | 57 | 58 | 59 | ## 2 使用 60 | ### 2.1 注册 61 | #### 2.1.1 页面注册 62 | 注册方式如下 63 | ```objectivec 64 | LJRouterInit(@"注释", 页面Key, (类型1)参数名1, (类型2)参数名2, ...) // 没有参数可以不写 65 | ``` 66 | 在某ViewController的类中写入以下代码即可完成详情页的注册 67 | ```objectivec 68 | LJRouterInit(@"详情页面", detailPage, (NSString*)someId) 69 | { 70 | self = [self init]; 71 | if (self) 72 | { 73 | // 初始化代码 74 | } 75 | return self; 76 | } 77 | ``` 78 | #### 2.1.2 action注册 79 | 注册方式如下 80 | ```objectivec 81 | LJRouterInit(@"注释", 页面Key, 返回值类型, (类型1)参数名1, (类型2)参数名2, ...) // 没有参数可以不写 82 | ``` 83 | 在任意类的代码中加入如下代码,即可完成一个判断登录状态action的注册. 84 | ``` objectivec 85 | LJRouterRegistAction(@"判断是否登录", isLogin, BOOL) 86 | { 87 | return _isLogin; 88 | } 89 | ``` 90 | 91 | #### 2.1.3 注册参数类型的支持 92 | 以上两种注册方式支持任意类型,包括block等. 93 | 1.另外如果您需要某Action与JS通信并返回值,则需要声明一个LJRouterCallbackBlock的参数,调用该参数可以将返回值传递回JS 94 | ``` objectivec 95 | LJRouterRegistAction(@"接收js命令", somejscmd, 96 | void, (NSString*)orignstring, 97 | (LJRouterCallbackBlock)callback) 98 | { 99 | callback([orignstring stringByAppendingString:@"_hello"], YES); 100 | } 101 | ``` 102 | 103 | 2.默认要求外部传递所有参数才可通过验证进入到注册的函数,如果您有一个参数不是必须的,则声明为 __nullable即可.(如果是值类型,nullable的变量会默认传0,或者{0,0}这样的结构体) 104 | ```objectivec 105 | LJRouterInit(@"详情页面", detailPage, (NSString*)someId, (__nullable NSString*)title) 106 | { 107 | self = [self init]; 108 | if (self) 109 | { 110 | if (title) 111 | { 112 | self.title = title; 113 | } 114 | // 初始化代码 115 | } 116 | return self; 117 | } 118 | ``` 119 | 3.如果你的某个注册函数,需要调用者,例如webview中调用设置页面title的action,那么这个action需要声明一个sender参数来接收调用方,sender类型可以是任意UIResponder的子类,或者声明为LJRouterSenderContext,如果直接声明为UIResponder的子类你需要对sender类型进行判断再进行相关的操作。 120 | 121 | 使用LJRouterSenderContext方式如下 122 | ```objectivec 123 | LJRouterRegistAction(@"设置UIWebView标题", setWebViewTitle2, 124 | void, (LJRouterSenderContext*)sender, (NSString*)title) 125 | { 126 | sender.contextViewController.title = title; 127 | } 128 | ``` 129 | 使用自定义UIResponder子类方式如下 130 | ```objectivec 131 | LJRouterRegistAction(@"设置UIWebView标题", setWebViewTitle, 132 | void, (UIWebView*)sender, (NSString*)title) 133 | { 134 | if (![sender isKindOfClass:[UIView class]]) 135 | { 136 | return; 137 | } 138 | UIResponder *responder = sender ; 139 | while (responder) 140 | { 141 | responder = [responder nextResponder]; 142 | if ([responder isKindOfClass:[UIViewController class]]) 143 | { 144 | UIViewController *vc = (id)responder; 145 | vc.title = title; 146 | } 147 | } 148 | } 149 | ``` 150 | #### 2.1.4 注册key的注意事项 151 | 1.请注意 key会编译为函数的一部分,所以只支持数字字符下划线. 152 | 2.不同的页面注册相同的key会在router启动阶段报错以保证安全. 153 | 3.同一个class可以对同一个key注册多次,但是需要有不同的参数列表,类似java的重载,但是如果某一个参数列表去掉__nullable的参数与另一参数列表相同的话,则有可能发生预期外的行为. 154 | 4.外部调用时,会忽略Key的大小写. 155 | #### 2.1.5 注册的附加属性 156 | 注册之后会默认生成文档,您可以在宏的第一个参数中填写更详尽的解释,同时如果有需求,您也可以为返回值和某个参数单独添加注释,这些注释只会在debug版本使用,并不会增加您发布版本的体积. 157 | 使用方式如下 158 | ```objectivec 159 | LJRouterRegistAction(@"attr测试action有参数", attr_action_1, 160 | NSInteger, (NSString*)something) 161 | { 162 | LJRouterReturnDescription(@"just return int");//为返回值加注释 163 | LJRouterParamDescription(something, @"something ");//为参数加注释 164 | return 0; 165 | } 166 | ``` 167 | 生成文档如下 168 | ```objectivec 169 | // action : attr测试action有参数 170 | // @param something something 171 | // @return NSInteger just return int 172 | LJRouterUseAction(attr_action_1, NSInteger, (NSString*)something); 173 | ``` 174 | 175 | 176 | ### 2.2 模块间调用 177 | 在-步骤2.1-注册过之后,build项目即可在 -步骤1.2- 设定的文件夹中产生出对应的头文件,示例如下: 178 | ```objectivec 179 | // 页面 : // webview// 外部url 180 | LJRouterUsePage(webview, (NSString*)url); 181 | // action : // 接收js命令// 接收一个字符串 添加_haha结尾 182 | LJRouterUseAction(somejscmd, void, (NSString*)str, (LJRouterCallbackBlock)callback); 183 | // action : // 设置UIWebView标题 184 | LJRouterUseAction(setWebViewTitle, void, (UIWebView*)sender, (NSString*)title); 185 | ``` 186 | ####2.2.1 跳转页面 187 | 直接复制头文件中的代码 到你的代码中即可调用 open_Key_controller_的c函数进行跳转 例如 188 | ```objectivec 189 | LJRouterUsePage(webview, (NSString*)url); 190 | - (void)click 191 | { 192 | NSString *url = @"xxxxxx"; 193 | open_webview_controller_with_htmlString(self, url); 194 | } 195 | ``` 196 | #### 2.2.2 获取页面对象 197 | 如果你想使用某一个页面的对象,而不是直接跳转,可以拷贝头文件的代码后面加Obj结尾,即可调用get_key_controller_的c函数进行获取 例如 198 | ```objectivec 199 | LJRouterUsePageObj(webview, (NSString*)url); 200 | - (void)click2 201 | { 202 | NSString *url = @"xxxxxx"; 203 | UIViewController *webVC = get_webview_controller_with_url(url); 204 | // do something ... 205 | } 206 | ``` 207 | #### 2.2.3 调用action 208 | 同2.2.1直接复制之后会产生 action_key_xxxx的c函数,直接调用即可 209 | 210 | ### 2.3 外部调用/动态调用 211 | 动态调用请使用下面函数进行调用 212 | ```objectivec 213 | - (BOOL)routerKey:(NSString *)key 214 | data:(NSDictionary *)data 215 | sender:(UIResponder *)sender 216 | pageBlock:(void(^)(__kindof UIViewController* viewController))pageBlock 217 | callbackBlock:(void(^)(NSString *key, 218 | NSString *value, 219 | NSString *data, 220 | BOOL complete))callbackBlock 221 | canNotRouterBlock:(void(^)(void))canNotRouterBlock; 222 | 223 | - (BOOL)routerUrlString:(NSString *)url 224 | sender:(UIResponder *)sender 225 | pageBlock:(void(^)(__kindof UIViewController* viewController))pageBlock 226 | callbackBlock:(void(^)(NSString *key, 227 | NSString *value, 228 | NSString *data, 229 | BOOL complete))callbackBlock 230 | canNotRouterBlock:(void(^)(void))canNotRouterBlock; 231 | 232 | ``` 233 | 以上两个函数的区别在于一个接受 key+data形式为数据 一个接受url为数据,内部实现上,url会转化为key+data的形式,默认拆解方式为,问号前面的部分为key,query部分拆解为data。 234 | 235 | 相同的参数部分 236 | **sender**:传入触发该action的UIResponder的子类。 237 | **pageBlock**:是该key分发成功并且为页面时的回调,你应该在这里进行跳转. 238 | **callbackBlock**:分发成功并且存在callbackblock时的回调,一般用该block与webview/js通讯 239 | **canNotRouterBlock**:是不能被分发时的回调 240 | 241 | webview拦截request的通讯方式实现如下 242 | ```objectivec 243 | - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 244 | { 245 | if ([request.URL.scheme hasPrefix:@"lianjia"]) 246 | { 247 | return ! 248 | [[LJRouter sharedInstance] routerUrlString:request.URL.absoluteString 249 | sender:webView 250 | pageBlock:^(__kindof UIViewController *viewController) { 251 | [[LJRouter sharedInstance] openViewController:viewController withSender:self]; 252 | } 253 | callbackBlock:^(NSString *key, 254 | NSString *value, 255 | NSString *data, 256 | BOOL complete) { 257 | if (value.length && data.length) 258 | { 259 | NSString *cmd = [[NSString alloc] initWithFormat:@"%@('%@');",value,data]; 260 | [self.webview stringByEvaluatingJavaScriptFromString:cmd]; 261 | } 262 | } 263 | canNotRouterBlock:nil]; 264 | } 265 | return YES; 266 | } 267 | ``` 268 | 269 | ## 3 导出文档的二次开发 270 | 271 | 你可以对导出文档部分进行二次开发,最便捷的方式是在项目中新建一个mac的target,然后将LJRouter/Export/下面的文件加入到target中,然后新建自定义的导出文档的文件,你可以使用 LJRouterExportModule.h中的loadAllRegItemByPath函数读取所有的注册信息.你需要自行管理文档文件,二次开发只提供的基础的读取注册信息的功能. 272 | 273 | ## 4 朋友写的一个源码解析 感兴趣的同学可以看看 274 | [LJRouter源码分析](http://drinking.github.io/ljrouter) 275 | 276 | -------------------------------------------------------------------------------- /_Pods.xcodeproj: -------------------------------------------------------------------------------- 1 | Example/Pods/Pods.xcodeproj -------------------------------------------------------------------------------- /build: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cd ${PODS_ROOT}/LJRouter/ 3 | if [ ! -x LJRouterExportDevDocument ]; 4 | then 5 | clang -mmacosx-version-min=10.5 -isysroot '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk' -framework Foundation LJRouter/ExportTool/LJRouterExportModule.m LJRouter/ExportDocument/LJRouterExportDevDocument.m -o LJRouterExportDevDocument 6 | fi 7 | cmd="./LJRouterExportDevDocument $*" 8 | echo $cmd 9 | eval $cmd 10 | --------------------------------------------------------------------------------