本文并不是要介紹什么是移動(dòng)端的路由,如果對(duì)這個(gè)概念不了解的話可以看下前人的文章,這里是 傳送門。
之所以決定要在項(xiàng)目里面加入這個(gè)機(jī)制,是源于我們運(yùn)營人員的一次偶然的需求,那就是他們希望能夠通過活動(dòng)頁的H5鏈接直接打開APP,并且定位到指定的頁面去,當(dāng)然通過傳統(tǒng)的方式也是可以一步一步的實(shí)現(xiàn),只是需要做特殊處理罷了,具體就不多說了。
但我們想做的徹底一點(diǎn),不如就此機(jī)會(huì)直接加入路由好了。沒錯(cuò),遇到問題當(dāng)你想的比別人多一兩步的時(shí)候就會(huì)看到一片新的天地。目前實(shí)現(xiàn)的功能已經(jīng)不僅僅是運(yùn)營人員所提及的那個(gè)小功能了,我們已經(jīng)實(shí)現(xiàn)了通過短信url短連接的方式訪問APP頁面的功能,這個(gè)功能很早之前就有了,但是我們卻一直沒有加入。并且對(duì)現(xiàn)有的代碼結(jié)構(gòu)也帶來了好的改變,那就是我們?cè)谶M(jìn)行頁面跳轉(zhuǎn)的時(shí)候,不需要再耦合具體的視圖控制器,而是通過路由進(jìn)行周轉(zhuǎn),這樣的話可以大大降低代碼的耦合度,當(dāng)然這方面目前還沒有推廣開,因?yàn)榇蠡锏木幋a習(xí)慣是比較難改變的。如果遇到一個(gè)強(qiáng)有力的領(lǐng) 導(dǎo)的話,說不定會(huì)推行這件事情。
我們的路由機(jī)制是建立在WLRRoute之上的,做這個(gè)第一步就是要搞清楚什么是頁面對(duì)應(yīng)的url,這里的url,并不是短連接里面所顯示的那樣子。比如http://m.vip.com/dcf6 這個(gè)是短信里的唯品會(huì)的鏈接,點(diǎn)擊后會(huì)進(jìn)入到他們的M站,而在進(jìn)入M站后會(huì)提示我們是否要在軟件中打開,所以這里的這個(gè)地址只是連接向唯品會(huì)M站的地址而已,通過后面所攜帶的dcf6參數(shù)再去他們的數(shù)據(jù)庫中去查詢?nèi)』厮鶎?duì)應(yīng)的APP中的路由地址。這個(gè)地址通常是 URL Schemes://url這樣的格式,前面的URL Schemes是每個(gè)APP所獨(dú)有的,比如我們的項(xiàng)目的URL Schemes是 abcmanager,而我們給首頁一個(gè)地址叫做homepage的話,那這個(gè)首頁所對(duì)應(yīng)的地址就應(yīng)該是 abcmanager://homepage, 只要在訪問到M站的時(shí)候,M站返回這個(gè)地址,我們就可以打開我們的軟件了。當(dāng)然在這之前會(huì)彈出一個(gè)確認(rèn)框,讓你確認(rèn)是否進(jìn)入APP。比如下圖。

搞清楚了這個(gè)頁面所對(duì)應(yīng)的路由是怎么回事就好辦了,接下來我們給幾乎能用的到的常用頁面進(jìn)行了路由的url注冊(cè),將它們寫入了一個(gè)plist文件中,一種是帶參數(shù)的,一種是不帶參數(shù)的,如下圖所示。


其中pjID是那個(gè)頁面所攜帶的參數(shù),為0-9之間的數(shù)字。
下面簡(jiǎn)要講一下基于WLRRoute我們所做的二次封裝。
先講一下幾個(gè)關(guān)鍵的類:
SpaceHomeRouter,繼承于WLRRouter。功能就是注冊(cè)u(píng)rl。
SpaceHomeRouteAnalysis,繼承于NSObject,用以解析外接傳入的路由信息。
SpaceHomeBaseRouteHandler,繼承于WLRRouteHandler,用于快速的處理handler,而無需像demo中所展示的那樣每一個(gè)都創(chuàng)建一個(gè)類。
最后就是RouterModel,用以承載plist文件中的數(shù)據(jù)。
具體代碼如下:
SpaceHomeRouter
- (id)init{
if (self = [super init]) {
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Route" ofType:@"plist"];
//字典數(shù)組
NSArray *dicArray = [NSArray arrayWithContentsOfFile:filePath];
//字典數(shù)組轉(zhuǎn)化為模型數(shù)組
_routeModelArray = [RouterModel mj_objectArrayWithKeyValuesArray:dicArray];
_allHandlers = [NSMutableArray array];
}
return self;
}
- (void)registerAllHandlers{
for (RouterModel *model in _routeModelArray) {
SpaceHomeBaseRouteHandler *routeHandler = [SpaceHomeBaseRouteHandler routeHandlerWithClsName:model.clsName ClsTab:model.clsTabPage];
[self registerHandler:routeHandler forRoute:[SHRouteBaseURL stringByAppendingString:model.clsUrl]];
[_allHandlers addObject:routeHandler];
}
}
SpaceHomeRouteAnalysis
- (void)handleURL:(NSURL *)url primitiveParameters:(NSDictionary *)primitiveParameters{
UITabBarController *tabVC = (UITabBarController *)(AppDelegate *)[UIApplication sharedApplication].delegate.window.rootViewController;
for (UINavigationController *nav in tabVC.viewControllers) {
[nav popToRootViewControllerAnimated:YES];
}
NSLog(@"SiginCallBack");
[[SpaceHomeRouter sharedSpaceHomeRouter] handleURL:url primitiveParameters:primitiveParameters targetCallBack:^(NSError *error, id responseObject) {
} withCompletionBlock:^(BOOL handled, NSError *error) {
NSLog(@"SiginHandleCompletion");
}];
}
SpaceHomeBaseRouteHandler
+ (instancetype)routeHandlerWithClsName:(NSString *)clsName ClsTab:(NSString *)clsTab{
return [[self alloc]initWithClsName:clsName clsTab:clsTab];
}
- (instancetype)initWithClsName:(NSString *)clsName clsTab:(NSString *)clsTab{
if (self = [super init]) {
_clsName = clsName;
_clsTab = clsTab;
}
return self;
}
-(UIViewController *)sourceViewControllerForTransitionWithRequest:(WLRRouteRequest *)request{
TabBarController *tabVC = (TabBarController *)[UIApplication sharedApplication].windows[0].rootViewController;
CommonNavigationViewController *nav = (CommonNavigationViewController *)tabVC.selectedViewController;
return nav;
}
-(UIViewController *)targetViewControllerWithRequest:(WLRRouteRequest *)request{
UIViewController * vc = [[NSClassFromString(_clsName) alloc]init];
return vc;
}
-(BOOL)transitionWithWithRequest:(WLRRouteRequest *)request sourceViewController:(UIViewController *)sourceViewController targetViewController:(UIViewController *)targetViewController isPreferModal:(BOOL)isPreferModal error:(NSError *__autoreleasing *)error{
if (_clsTab.intValue>0) {
TabBarController *tabVC = (TabBarController *)[UIApplication sharedApplication].windows[0].rootViewController;
tabVC.selectedIndex = _clsTab.intValue-1;
return YES;
}
if (isPreferModal||![sourceViewController isKindOfClass:[CommonNavigationViewController class]]) {
[sourceViewController presentViewController:targetViewController animated:YES completion:nil];
}
else if ([sourceViewController isKindOfClass:[CommonNavigationViewController class]]){
CommonNavigationViewController * nav = (CommonNavigationViewController *)sourceViewController;
[nav pushViewController:targetViewController animated:YES];
}
return YES;
}
最后在Appdelegate中的方法中加入下面一句代碼就可以了。
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options {
[[SpaceHomeRouteAnalysis sharedSpaceHomeRouteAnalysis]handleURL:url primitiveParameters:options];
}