精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

一步步構建iOS路由

移動開發 iOS
路由層其實在邏輯上的設計都是一樣的,關于對界面跳轉的實現部分卻與Android平臺和iOS平臺上的導航機制有著非常緊密的關系,Android操作系統有著天然的架構優勢,Intent機制可以協助應用間的交互與通訊,是對調用組件和數據傳遞的描述,本身這種機制就解除了代碼邏輯和界面之間的依賴關系,只有數據依賴。而iOS的界面導航和轉場機制則大部分依賴UI組件各自的實現,所以如何解決這個問題,iOS端路由的實現則比較有代表性。

接上一篇移動端路由層設計

為啥要說iOS路由呢?

路由層其實在邏輯上的設計都是一樣的,關于對界面跳轉的實現部分卻與Android平臺和iOS平臺上的導航機制有著非常緊密的關系,Android操作系統有著天然的架構優勢,Intent機制可以協助應用間的交互與通訊,是對調用組件和數據傳遞的描述,本身這種機制就解除了代碼邏輯和界面之間的依賴關系,只有數據依賴。而iOS的界面導航和轉場機制則大部分依賴UI組件各自的實現,所以如何解決這個問題,iOS端路由的實現則比較有代表性。

其實說白一點,路由層解決的核心問題就是原來界面或者組件之間相互調用都必須相互依賴,需要導入目標的頭文件、需要清楚目標對象的邏輯,而現在全部都通過路由中轉,只依賴路由,或者依靠一些消息傳遞機制連路由都不依賴。其次,路由的核心邏輯就是目標匹配,對于外部調用的情況來說,URL如何匹配Handler是最為重要的,匹配就必然用到正則表達式。了解這些關鍵點以后就有了設計的目的性,let‘s do it~

設計類圖: 

 

 

設計類圖 

RouteClassMap.png

這里面有如下幾個類:

  1. WLRRouteRequest,路由層的請求,無論是跨應用的外部調用還是內部調用,最后都形成一個路由請求,該請求包含了URL上的queryparameters和路徑參數,還有內部調用時直接傳入的原生參數,還有請求發起者對目標預留的回調block
  2. WLRRouteHandler,路由層的handler處理,handler接收一個WLRRouteRequest對象,來完成是否是界面跳轉,還是組件加載,還是內部邏輯
  3. WLRRouter,路由核心對象,內部持有注冊的Handler,比方說負責界面跳轉的Handler,負責組件加載的Handler,負責API的Handler等等,路由的作用就是將外部調用傳入的URL或者是內部調用傳入的target,在內部匹配上對應的handler,然后調用生命周期方法,完成處理過程,當然,圖中還有route的中間件,實際上是預留AOP的口子,方面后期擴展
  4. WLRRouteMatcher,用以處理外部調用的URL是否能與預設的正則表達式匹配,在WLRRouter中,每一次注冊一個handler,都會用一個URL匹配的表達式生成一個WLRRouteMatcher
  5. WLRRegularExpression,繼承NSRegularExpression,用以匹配URL,WLRRouteMatcher內部有一個WLRRegularExpression對象,WLRRouteMatcher接受一個URL,會使用WLRRegularExpression生成一個WLRMatchResult對象,來確定是否匹配成功,如果匹配成果則將URL上的路徑參數給取出來
  6. WLRMatchResult,用以描述WLRRegularExpression的匹配結果,包含路徑參數

工作流程:

  1. App啟動實例化WLRRouter對象
  2. 實例化WLRRouteHandler對象
  3. WLRRouter對象掛載WLRRouteHandler實例與URL的表達式相對應,WLRRouter內部生成一個WLRRouteMatcher對象,與URL的表達式相對應
  4. 外部調用的URL和callback傳入WLRRouter對象
  5. WLRRouter對象遍歷內部持有的URL的匹配表達式,并找到每一個WLRRouteMatcher對象,將URL傳入看是否能返回WLRRouteRequest對象
  6. 將WLRRouteRequest對象傳入對應的WLRRouteHandler對象
  7. WLRRouteHandler對象根據WLRRouteRequest尋找到TargetViewController和SourceViewController,在生命周期函數里,完成參數傳遞與視圖轉場

WLRRouteRequest:

了解了以上,我們從WLRRouteRequest入手。

其實WLRRouteRequest跟NSURLRequest差不多,不過WLRRouteRequest繼承NSObject,實現NSCopying協議,大概如下:

  1. #import 
  2.   
  3. @interface WLRRouteRequest : NSObject 
  4. //外部調用的URL 
  5. @property (nonatomic, copy, readonly) NSURL *URL; 
  6. //URL表達式,比方說調用登錄界面的表達式可以為:AppScheme://user/login/138********,那URL的匹配表達式可以是:/login/:phone([0-9]+),路徑必須以/login開頭,后面接0-9的電話號碼數字,當然你也可以直接把電話號碼的正則匹配寫全 
  7. @property(nonatomic,copy)NSString * routeExpression; 
  8. //如果URL是AppScheme://user/login/138********?/callBack="",那么這個callBack就出現在這 
  9. @property (nonatomic, copy, readonly) NSDictionary *queryParameters; 
  10. //這里面會出現{@"phone":@"138********"
  11. @property (nonatomic, copy, readonly) NSDictionary *routeParameters; 
  12. //這里面存放的是內部調用傳遞的原生參數 
  13. @property (nonatomic, copy, readonly) NSDictionary *primitiveParams; 
  14. //自動檢測竊取回調的callBack 的Url 
  15. @property (nonatomic, strong) NSURL *callbackURL; 
  16. //目標的viewcontrolller或者是組件可以通過這個 
  17. @property(nonatomic,copy)void(^targetCallBack)(NSError *error,id responseObject); 
  18. //用以表明該request是否被消費 
  19. @property(nonatomic)BOOL isConsumed; 
  20. //簡便方法,用以下標法取參數 
  21. - (id)objectForKeyedSubscript:(NSString *)key
  22. //初始化方法 
  23. -(instancetype)initWithURL:(NSURL *)URL routeExpression:(NSString *)routeExpression routeParameters:(NSDictionary *)routeParameters primitiveParameters:(NSDictionary *)primitiveParameters targetCallBack:(void(^)(NSError * error,id responseObject))targetCallBack; 
  24. -(instancetype)initWithURL:(NSURL *)URL; 
  25. //默認完成目標的回調 
  26. -(void)defaultFinishTargetCallBack; 
  27. @end 

NSURLRequest其實應該是個值類型的對象,所以實現拷貝協議,該對象的實現部分沒有什么可講的,對照源代碼查閱即可。

WLRRouteHandler

  1. #import 
  2. @class WLRRouteRequest; 
  3. @interface WLRRouteHandler : NSObject 
  4. //即將handle某一個請求 
  5. - (BOOL)shouldHandleWithRequest:(WLRRouteRequest *)request; 
  6. //根據request取出調用的目標視圖控制器 
  7. -(UIViewController *)targetViewControllerWithRequest:(WLRRouteRequest *)request; 
  8. //根據request取出來源的視圖控制器 
  9. -(UIViewController *)sourceViewControllerForTransitionWithRequest:(WLRRouteRequest *)request; 
  10. //開始進行轉場 
  11. -(BOOL)transitionWithRequest:(WLRRouteRequest *)request error:(NSError *__autoreleasing *)error; 
  12. @end 

當WLRRouter對象完成了URL的匹配生成Request,并尋找到Handler的時候,首先會調用- (BOOL)shouldHandleWithRequest:(WLRRouteRequest *)request;,來確定handler是否愿意處理,如果愿意,則調用-(BOOL)transitionWithRequest:(WLRRouteRequest *)request error:(NSError *__autoreleasing *)error;,內部則通過便利方法獲取targetViewController與SourceViewController,然后進行轉場,核心方法的實現為:

  1. -(BOOL)transitionWithRequest:(WLRRouteRequest *)request error:(NSError *__autoreleasing *)error{ 
  2.     UIViewController * sourceViewController = [self sourceViewControllerForTransitionWithRequest:request]; 
  3.     UIViewController * targetViewController = [self targetViewControllerWithRequest:request]; 
  4.     if ((![sourceViewController isKindOfClass:[UIViewController class]])||(![targetViewController isKindOfClass:[UIViewController class]])) { 
  5.         *error = [NSError WLRTransitionError]; 
  6.         return NO
  7.     } 
  8.     if (targetViewController != nil) { 
  9.         targetViewController.wlr_request = request; 
  10.     } 
  11.     if ([self preferModalPresentationWithRequest:request]||![sourceViewController isKindOfClass:[UINavigationController class]]) { 
  12.         [sourceViewController presentViewController:targetViewController animated:YES completion:nil]; 
  13.     } 
  14.     else if ([sourceViewController isKindOfClass:[UINavigationController class]]){ 
  15.         UINavigationController * nav = (UINavigationController *)sourceViewController; 
  16.         [nav pushViewController:targetViewController animated:YES]; 
  17.     } 
  18.     return YES; 
  19. - (BOOL)preferModalPresentationWithRequest:(WLRRouteRequest *)request;{ 
  20.     return NO

這里根據SourceController的類型進行判斷,其實request對象的信息足夠可以判斷目標視圖應該如何打開,從本質上來講,URL的匹配表達式是跟業務強關聯的也是跟UI交互邏輯強關聯的,transitionWithRequest方法實現里,你大可以繼承一下,然后重寫轉場過程,甚至你可以在這自己設置iOS7自定義的轉場,提供動畫控制器和實現轉場協議的對象,進而可以整體的控制Appp內部的實現。

WLRRegularExpression

該類繼承NSRegularExpression

  1. #import 
  2. @class WLRMatchResult; 
  3. @interface WLRRegularExpression : NSRegularExpression 
  4. //傳入一個URL返回一個匹配結果 
  5. -(WLRMatchResult *)matchResultForString:(NSString *)string; 
  6. //根據一個URL的表達式創建一個WLRRegularExpression實例 
  7. +(WLRRegularExpression *)expressionWithPattern:(NSString *)pattern; 
  8. @end 

該對象主要的功能是將一個URL傳入查看是否匹配,并且將表達式上聲明的路徑參數從URL上取下來。

比說,我們設置的URL匹配的表達式是: login/:phone([0-9]+),那AppScheme://user/login/138** 這樣的URL應該是匹配,并且將138的手機號取出來,對應到phone上,這個過程必須用到正則表達式的分組提取子串的功能,:phone是約定好的提取子串的值對應的key的名字,其實這個url的正則表達式應該是: /login/([0-9]+)$,那么WLRRegularExpression對象需要知道需要提取所有子串的key還有將URL匹配的表達式轉換為真正的正則表達式。

  1. -(instancetype)initWithPattern:(NSString *)pattern options:(NSRegularExpressionOptions)options error:(NSError * _Nullable __autoreleasing *)error{ 
  2. //初始化方法中將URL匹配的表達式pattern轉換為真正的正則表達式 
  3.     NSString *transformedPattern = [WLRRegularExpression transfromFromPattern:pattern]; 
  4. //用轉化后的結果初始化父類 
  5.     if (self = [super initWithPattern:transformedPattern options:options error:error]) { 
  6. //同時將需要提取的子串的值的Key保存到數組中 
  7.         self.routerParamNamesArr = [[self class] routeParamNamesFromPattern:pattern]; 
  8.     } 
  9.     return self; 
  10. //轉換為正則表達式 
  11. +(NSString*)transfromFromPattern:(NSString *)pattern{ 
  12. //將pattern拷貝 
  13.     NSString * transfromedPattern = [NSString stringWithString:pattern]; 
  14. //利用:[a-zA-Z0-9-_][^/]+這個正則表達式,將URL匹配的表達式的子串key提取出來,也就是像 /login/:phone([0-9]+)/:name[a-zA-Z-_]這樣的pattern,需要將:phone([0-9]+)和:name[a-zA-Z-_]提取出來 
  15.     NSArray * paramPatternStrings = [self paramPatternStringsFromPattern:pattern]; 
  16.     NSError * err; 
  17. //再根據:[a-zA-Z0-9-_]+這個正則表達式,將帶有提取子串的key全部去除,比如將:phone([0-9]+)去除:phone改成([0-9]+) 
  18.     NSRegularExpression * paramNamePatternEx = [NSRegularExpression regularExpressionWithPattern:WLRRouteParamNamePattern options:NSRegularExpressionCaseInsensitive error:&err]; 
  19.     for (NSString * paramPatternString in paramPatternStrings) { 
  20.         NSString * replaceParamPatternString = [paramPatternString copy]; 
  21.         NSTextCheckingResult * foundParamNamePatternResult =[paramNamePatternEx matchesInString:paramPatternString options:NSMatchingReportProgress range:NSMakeRange(0, paramPatternString.length)].firstObject; 
  22.         if (foundParamNamePatternResult) { 
  23.             NSString *paramNamePatternString =[paramPatternString substringWithRange: foundParamNamePatternResult.range]; 
  24.             replaceParamPatternString = [replaceParamPatternString stringByReplacingOccurrencesOfString:paramNamePatternString withString:@""]; 
  25.         } 
  26.         if (replaceParamPatternString.length == 0) { 
  27.             replaceParamPatternString = WLPRouteParamMatchPattern; 
  28.         } 
  29.         transfromedPattern = [transfromedPattern stringByReplacingOccurrencesOfString:paramPatternString withString:replaceParamPatternString]; 
  30.     } 
  31.     if (transfromedPattern.length && !([transfromedPattern characterAtIndex:0] == '/')) { 
  32.         transfromedPattern = [@"^" stringByAppendingString:transfromedPattern]; 
  33.     } 
  34. //最后結尾要用$符號 
  35.     transfromedPattern = [transfromedPattern stringByAppendingString:@"$"]; 
  36. //最后會將/login/:phone([0-9]+)轉換為login/([0-9]+)$ 
  37.     return transfromedPattern; 

在Matcher對象匹配一個URL的時候

  1. -(WLRMatchResult *)matchResultForString:(NSString *)string{ 
  2. //首先通過自身方法將URL進行匹配得出NSTextCheckingResult結果的數組 
  3.     NSArray * array = [self matchesInString:string options:0 range:NSMakeRange(0, string.length)]; 
  4.     WLRMatchResult * result = [[WLRMatchResult alloc]init]; 
  5.     if (array.count == 0) { 
  6.         return result; 
  7.     } 
  8.     result.match = YES; 
  9.     NSMutableDictionary * paramDict = [NSMutableDictionary dictionary]; 
  10. //遍歷NSTextCheckingResult結果 
  11.     for (NSTextCheckingResult * paramResult in array) { 
  12. //再便利根據初始化的時候提取的子串的Key的數組 
  13.         for (int i = 1; i<paramResult.numberOfRanges&&i <= self.routerParamNamesArr.count;i++ ) { 
  14.             NSString * paramName = self.routerParamNamesArr[i-1]; 
  15. //將值取出,然后將key和value放入到paramDict 
  16.             NSString * paramValue = [string substringWithRange:[paramResult rangeAtIndex:i]]; 
  17.             [paramDict setObject:paramValue forKey:paramName]; 
  18.         } 
  19.     } 
  20. //最后賦值給WLRMatchResult對象 
  21.     result.paramProperties = paramDict; 
  22.     return result; 

核心代碼總共80多行,源碼大家可以詳閱

WLRRouteMatcher

  1. #import 
  2. @class WLRRouteRequest; 
  3. @interface WLRRouteMatcher : NSObject 
  4. //傳入URL匹配的表達式,獲取一個matcher實例 
  5. +(instancetype)matcherWithRouteExpression:(NSString *)expression; 
  6. //傳入URL,如果能匹配上,則生成WLRRouteRequest對象,同時將各種參數解析好交由WLRRouteRequest攜帶 
  7. -(WLRRouteRequest *)createRequestWithURL:(NSURL *)URL primitiveParameters:(NSDictionary *)primitiveParameters targetCallBack:(void(^)(NSError *, id responseObject))targetCallBack; 
  8. @end 

屬性有如下:

  1. //scheme 
  2. @property(nonatomic,copy) NSString * scheme; 
  3. //WLRRegularExpression的實例 
  4. @property(nonatomic,strong)WLRRegularExpression * regexMatcher; 
  5. //匹配的表達式 
  6. @property(nonatomic,copy)NSString * routeExpressionPattern; 

初始化方法:

  1. -(instancetype)initWithRouteExpression:(NSString *)routeExpression{ 
  2.     if (![routeExpression length]) { 
  3.         return nil; 
  4.     } 
  5.     if (self = [super init]) { 
  6. //將scheme與path部分分別取出 
  7.         NSArray * parts = [routeExpression componentsSeparatedByString:@"://"]; 
  8.         _scheme = parts.count>1?[parts firstObject]:nil; 
  9.         _routeExpressionPattern =[parts lastObject]; 
  10. //將path部分當做URL匹配表達式生成WLRRegularExpression實例 
  11.         _regexMatcher = [WLRRegularExpression expressionWithPattern:_routeExpressionPattern]; 
  12.     } 
  13.     return self; 

匹配方法:

  1. -(WLRRouteRequest *)createRequestWithURL:(NSURL *)URL primitiveParameters:(NSDictionary *)primitiveParameters targetCallBack:(void (^)(NSError *, id))targetCallBack{ 
  2.     NSString * urlString = [NSString stringWithFormat:@"%@%@",URL.host,URL.path]; 
  3.     if (self.scheme.length && ![self.scheme isEqualToString:URL.scheme]) { 
  4.         return nil; 
  5.     } 
  6. //調用self.regexMatcher將URL傳入,獲取WLRMatchResult結果,看是否匹配 
  7.     WLRMatchResult * result = [self.regexMatcher matchResultForString:urlString]; 
  8.     if (!result.isMatch) { 
  9.         return nil; 
  10.     } 
  11. //如果匹配,則將result.paramProperties路徑參數傳入,初始化一個WLRRouteRequest實例 
  12.     WLRRouteRequest * request = [[WLRRouteRequest alloc]initWithURL:URL routeExpression:self.routeExpressionPattern routeParameters:result.paramProperties primitiveParameters:primitiveParameters targetCallBack:targetCallBack]; 
  13.     return request; 

WLRRouter

  1. @class WLRRouteRequest; 
  2. @class WLRRouteHandler; 
  3. @interface WLRRouter : NSObject 
  4. //注冊block回調的URL匹配表達式,可用作內部調用 
  5. -(void)registerBlock:(WLRRouteRequest *(^)(WLRRouteRequest * request))routeHandlerBlock forRoute:(NSString *)route; 
  6. //注冊一個WLRRouteHandler對應的URL匹配表達式route 
  7. -(void)registerHandler:(WLRRouteHandler *)handler forRoute:(NSString *)route; 
  8. //判斷url是否可以被handle 
  9. -(BOOL)canHandleWithURL:(NSURL *)url; 
  10. -(void)setObject:(id)obj forKeyedSubscript:(NSString *)key
  11. -(id)objectForKeyedSubscript:(NSString *)key
  12. //調用handleURL方法,傳入URL、原生參數和targetCallBack和完成匹配的completionBlock 
  13. -(BOOL)handleURL:(NSURL *)URL primitiveParameters:(NSDictionary *)primitiveParameters targetCallBack:(void(^)(NSError *, id responseObject))targetCallBack withCompletionBlock:(void(^)(BOOL handled, NSError *error))completionBlock; 

在實現部分,有三個屬性:

  1. //每一個URL的匹配表達式route對應一個matcher實例,放在字典中 
  2. @property(nonatomic,strong)NSMutableDictionary * routeMatchers; 
  3. //每一個URL匹配表達式route對應一個WLRRouteHandler實例 
  4. @property(nonatomic,strong)NSMutableDictionary * routeHandles; 
  5. //每一個URL匹配表達式route對應一個回調的block 
  6. @property(nonatomic,strong)NSMutableDictionary * routeblocks; 

在Route掛在Handler和回調的block的時候:

  1. -(void)registerBlock:(WLRRouteRequest *(^)(WLRRouteRequest *))routeHandlerBlock forRoute:(NSString *)route{ 
  2.     if (routeHandlerBlock && [route length]) { 
  3. //首先添加一個WLRRouteMatcher實例 
  4.         [self.routeMatchers setObject:[WLRRouteMatcher matcherWithRouteExpression:route] forKey:route]; 
  5. //刪除route對應的handler對象 
  6.         [self.routeHandles removeObjectForKey:route]; 
  7. //將routeHandlerBlock和route存入對應關系的字典中 
  8.         self.routeblocks[route] = routeHandlerBlock; 
  9.     } 
  10. -(void)registerHandler:(WLRRouteHandler *)handler forRoute:(NSString *)route{ 
  11.     if (handler && [route length]) { 
  12. //首先生成route對應的WLRRouteMatcher實例 
  13.         [self.routeMatchers setObject:[WLRRouteMatcher matcherWithRouteExpression:route] forKey:route]; 
  14. //刪除route對應的block回調 
  15.         [self.routeblocks removeObjectForKey:route]; 
  16. //設置route對應的handler 
  17.         self.routeHandles[route] = handler; 
  18.     } 

接下來完善handle方法: 

 

 

  

 

 

 

以上我們可以看到,Route將匹配的邏輯單獨封裝到WLRRouteMatcher對象中,將匹配后的結果生成WLRRouteRequest實例以攜帶足夠完整的數據,同時將真正處理視圖控制器的轉場或者是組件的加載或者是未來可能拓展的handle業務封裝到WLRRouteHandler實例中,匹配邏輯對應的處理邏輯干凈分離,匹配邏輯可單獨塑造業務匹配,處理邏輯可以通過繼承擴展或者沖洗WLRRouteHandler的生命周期函數來更好的處理回調業務。如果WLRRouteHandler不能提供足夠多的擴展性,則可以使用block回調最大限度的進行擴展。

以上,就是路由部分的整體實現。

轉場的擴展

在WLRRouteHandler中,其實我們可以單獨控制路由經過的頁面跳轉的轉場。

  1. -(UIViewController *)targetViewControllerWithRequest:(WLRRouteRequest *)request{ 
  2. -(UIViewController *)sourceViewControllerForTransitionWithRequest:(WLRRouteRequest *)request{ 
  3. -(BOOL)transitionWithRequest:(WLRRouteRequest *)request error:(NSError *__autoreleasing *)error{ 
  4.   
  5.  

這樣的生命周期函數是不是很像UIViewControllerContextTransitioning轉場上下文的協議的設定?- (nullable __kindof UIViewController *)viewControllerForKey:(UITransitionContextViewControllerKey)key;方法使上下文提供目標控制器和源控制器,其實在handler中你完全可以自定義一個子類,在transitionWithRequest方法里,設置遵守UIViewControllerTransitioningDelegate的代理,然后在此提供遵守 UIViewControllerAnimatedTransitioning的動畫控制器,然后自定義轉場上下文,實現自定義UI轉場,而對應的匹配邏輯是與此無關的,我們就可以在路由曾控制全局的頁面轉場效果。對自定義轉場不太熟悉的同學請移步我之前的文章:

ContainerViewController的ViewController 轉場

路由的安全

有兩個方面可以去做

  1. WLRRouteHandler實例中, -(BOOL)shouldHandleWithRequest:(WLRRouteRequest *)request中可以檢測request中的參數,比方說效驗source或者是效驗業務參數完整等
  2. WLRRouter實例中handleURL方法,將在隨后的WLRRoute的0.0.2版本中加入中間件的支持,就是在找到handler之前,將按照中間件注冊的順序回調中間件,而我們可以在中間件中實現風控業務、認證機制、加密驗簽等等

路由的效率

目前我們實現的路由是一個同步阻塞型的,在處理并發的時候可能會出現一些問題,或者是在注冊比較多的route表達式以后,遍歷和匹配的過程會損耗性能,比較好的實現方式是,將Route修改成異步非阻塞型的,但是API全部要換成異步API,起步我們先把同步型的搞定,隨后慢慢提供異步版本的路由~

路由的使用

在大部分App實踐MVVM架構或者更為復雜的VIPER架構的時候,除了迫切需要一個比較解耦的消息傳遞機制,如何更好的剝離目標實體的獲取和配合UIKit這一層的轉場邏輯是一項比較復雜的挑戰,路由實際上是充當MVVM的ViewModel中比較解耦的目標獲取邏輯和VIPER中Router層,P與V的調用全部靠Router轉發。

在實施以組件化為目的的工程化改造中,如何抽離單獨業務為組件,比較好的管理業務與業務之間的依賴,就必須使用一個入侵比較小的Route,WLRRoute入侵的地方在于WLRRouteHandler的transitionWithRequest邏輯中,通過一個UIViewController的擴展,給 targetViewController.wlr_request = request;設置了WLRRouteRequest對象給目標業務,但雖然如此,你依舊可以重寫WLRRouteHandler的transitionWithRequest方法,來構建你自己參數傳遞方式,這一點完全取決于你如何更好的使得業務無感知而使用路由。

最后附上代碼地址:

喜歡的來個星吧… 

https://github.com/Neojoke/WLRRoute

責任編輯:龐桂玉 來源: iOS大全
相關推薦

2019-04-01 10:15:02

2019-07-09 15:23:22

Docker存儲驅動

2019-03-05 14:09:27

Docker存儲容器

2009-12-17 16:36:23

無線路由設置密碼

2018-12-24 10:04:06

Docker存儲驅動

2010-08-10 11:31:36

路由器配置NAT

2010-03-04 16:28:17

Android核心代碼

2016-11-02 18:54:01

javascript

2017-12-25 11:50:57

LinuxArch Linux

2009-11-17 08:42:57

2011-09-05 12:36:08

路由器限速linux路由器

2011-05-10 10:28:55

2024-08-30 08:30:29

CPU操作系統寄存器

2024-09-30 09:56:59

2024-10-30 16:01:31

2025-11-19 09:18:44

CeleryPython機器學習

2020-12-24 11:19:55

JavaMapHashMap

2015-07-27 16:06:16

VMware Thin虛擬化

2024-08-06 09:29:54

程序機器指令字符串

2018-07-13 15:36:52

點贊
收藏

51CTO技術棧公眾號

国产男女激情视频| 国产精品美女诱惑| 亚洲天堂网av在线| 天堂精品久久久久| 午夜成人免费视频| 日本视频一区二区在线观看| 亚洲一区二区三区高清视频| 午夜精品剧场| 亚洲天堂免费视频| 中文字幕第六页| 亚洲美女炮图| 亚洲欧洲成人精品av97| 国产高清在线精品一区二区三区| 九九精品免费视频| 亚洲国产日韩欧美在线| 日韩精品久久久久| 激情五月婷婷基地| 中文在线аv在线| 亚洲欧美日韩综合aⅴ视频| 精品国产乱码久久久久久108| 亚洲精品91天天久久人人| 欧美69wwwcom| 国产性色av一区二区| 精品国产aⅴ一区二区三区东京热| 亚洲黄色免费av| 亚洲日本一区二区| 欧美一区二区三区四区五区六区| av 一区二区三区| 久色成人在线| 午夜精品国产精品大乳美女| 日韩在线视频免费看| 美女亚洲一区| 欧美成人精品高清在线播放 | 免费在线欧美黄色| 欧美日韩成人在线视频| 国产一级淫片久久久片a级| 久久中文字幕导航| 欧美va亚洲va香蕉在线 | 国产福利一区二区三区在线视频| 国产成人鲁鲁免费视频a| 久久视频免费在线观看| 影音先锋日韩精品| 日韩中文字幕网址| 成人无码av片在线观看| 婷婷综合成人| 亚洲精品久久久久久久久久久久久 | 丰乳肥臀在线| 一区二区三区四区视频精品免费| 亚洲欧美日韩国产yyy| 国产剧情在线观看| 久久精品免费在线观看| 久热国产精品视频一区二区三区| 亚洲 欧美 自拍偷拍| 成人免费精品视频| 国产精品免费观看高清| 成人午夜福利视频| 粉嫩av一区二区三区粉嫩| 51国产成人精品午夜福中文下载 | 日韩精品中文字幕在线不卡尤物| 日本在线播放一区二区| 91精品福利观看| 在线播放91灌醉迷j高跟美女 | 免费高清一区二区三区| 色老头在线观看| 亚洲国产精品尤物yw在线观看| 黑人巨茎大战欧美白妇| 污污的网站在线免费观看| 亚洲伦在线观看| 伊人再见免费在线观看高清版| 18videosex性欧美麻豆| 亚洲午夜精品网| 水蜜桃色314在线观看| 欧美一级鲁丝片| 色一区在线观看| 天天爽人人爽夜夜爽| 日韩av懂色| 欧美大片在线观看一区二区| 国产女人18毛片水真多18| 日本国产精品| 中文字幕精品—区二区| 国产性生活大片| 精品69视频一区二区三区Q| 欧美一级片在线播放| 中文字幕理论片| 国产精品91一区二区| 国产精品我不卡| 黄色的视频在线免费观看| 中文字幕巨乱亚洲| 真人做人试看60分钟免费| 乡村艳史在线观看| 精品视频色一区| 五月六月丁香婷婷| 欧美一级色片| 日韩视频―中文字幕| 国产精品变态另类虐交| 日韩福利电影在线观看| 成人av在线天堂| 日韩中文字幕影院| 国产精品天天摸av网| 国产在线视频在线| 日本欧美韩国| 亚洲第一网站免费视频| 91导航在线观看| 亚洲国产专区校园欧美| 国产精品入口夜色视频大尺度| 国产黄色大片网站| 国产丝袜美腿一区二区三区| a级片一区二区| 欧美专区福利免费| 欧美一卡2卡3卡4卡| 公侵犯人妻一区二区三区| 91精品福利| 国产成人精品网站| 亚洲精品97久久中文字幕| 国产日韩欧美在线一区| 欧美国产综合在线| 日韩欧国产精品一区综合无码| 亚洲精美色品网站| 久久免费看少妇高潮v片特黄| 国产伦理一区| 福利精品视频| 成人日日夜夜| 在线看不卡av| 亚洲黄色在线网站| 韩国一区二区三区在线观看| 国产在线一区二区三区| 黄色免费在线播放| 欧美性xxxxxxxxx| 9.1在线观看免费| 亚洲精品a级片| 国产精品久久久久久久久久久久久久 | 亚洲欧美日韩国产综合精品二区| 91成人免费视频| 蜜桃av在线免费观看| 日本丶国产丶欧美色综合| 国产chinese中国hdxxxx| 在线国产一区二区| 91精品免费看| 欧美jizz18hd性欧美| 在线亚洲高清视频| 亚洲理论片在线观看| 亚洲一区国产| 国产伦精品一区二区三区高清版 | 日韩在线视频第一页| 一区二区三区四区蜜桃| 免费黄视频在线观看| 欧美1区2区3区| 91在线播放视频| 四虎影院观看视频在线观看| 3d动漫精品啪啪一区二区竹菊| 黄色国产在线播放| 麻豆精品在线观看| 亚洲午夜精品福利| 日韩伦理一区二区| 欧美成人精品不卡视频在线观看| 国产精品久久久久久免费播放| 国产精品乱码久久久久久 | 懂色av一区二区三区蜜臀| 日本丰满大乳奶| 韩国三级大全久久网站| 欧美巨大黑人极品精男| 亚洲av无码国产精品久久不卡| 一区二区三区在线观看欧美| 国产麻豆剧传媒精品国产| 一区久久精品| 久久综合九九| 精品自拍视频| 欧美成人激情视频免费观看| 丰满少妇高潮在线观看| 天天综合天天综合色| 免费毛片视频网站| 久久精品二区亚洲w码| 9l视频自拍9l视频自拍| 久久a级毛片毛片免费观看| 2019精品视频| youjizz在线播放| 9191久久久久久久久久久| 久久久久久欧美精品se一二三四| 成人美女在线观看| 黑鬼大战白妞高潮喷白浆| 伊人久久大香线蕉av不卡| 国产精品久久久久久久久影视 | 国产xxxxx视频| 2023国产精品久久久精品双| 国产精品一区在线观看| 久久99久久99精品免观看软件| 中文字幕一区二区三区电影| 亚洲av无码一区二区乱子伦| 精品久久香蕉国产线看观看gif| 欧美激情视频二区| 国产成人午夜视频| 免费观看成人在线视频| 欧美久久九九| 日韩久久久久久久| 亚洲高清在线一区| 国产99久久精品一区二区| 国产在线高潮| 亚洲精品在线观看www| 国产av一区二区三区| 欧美性xxxx极品hd满灌| 中文字幕另类日韩欧美亚洲嫩草| 91视频在线观看免费| 中文字幕色网站| 亚洲综合激情| 精品一区二区三区毛片| 久久99影视| 国产成人亚洲欧美| 欧美一级做a| 2025国产精品视频| 午夜小视频在线观看| 在线精品视频视频中文字幕| 国产综合在线播放| 制服丝袜中文字幕亚洲| 日韩黄色一级视频| 婷婷中文字幕综合| www.av视频| 国产精品国产三级国产aⅴ原创| 亚洲av成人无码一二三在线观看| 国产一区激情在线| 69久久久久久| 久久福利影视| 国产精品12345| 重囗味另类老妇506070| 丝袜美腿玉足3d专区一区| 日韩美女国产精品| 99在线免费观看视频| 羞羞视频在线观看一区二区| 欧美在线中文字幕| h片在线观看下载| 免费91在线视频| 黄色网页网址在线免费| 在线视频欧美日韩| 久久精品蜜桃| 亚洲欧美中文日韩在线| 五月婷婷久久久| 日韩美女视频在线| 精品人妻aV中文字幕乱码色欲| 欧美三级韩国三级日本一级| 乱子伦一区二区三区| 欧美性高潮床叫视频| 青青国产在线观看| 精品欧美aⅴ在线网站| 国产午夜精品无码一区二区| 一区二区高清视频在线观看| 黄色一级片在线| 一区二区不卡在线视频 午夜欧美不卡在| 色欲一区二区三区精品a片| 国产精品三级av在线播放| eeuss中文字幕| 国产精品免费久久久久| 婷婷国产成人精品视频| 国产精品久久免费看| 国产精品www爽爽爽| 欧美经典一区二区三区| 在线免费看视频| 亚洲欧美中日韩| 91插插插插插插| 亚洲最大成人网4388xx| 久久精品视频9| 午夜av一区二区| 日产精品久久久| 色呦呦国产精品| 在线观看免费观看在线| 91精品午夜视频| 好吊色视频一区二区| 亚洲国产第一页| 日本电影一区二区在线观看| 国产亚洲综合久久| 麻豆传媒视频在线| 欧美黑人国产人伦爽爽爽| 青春草免费在线视频| 66m—66摸成人免费视频| 六月婷婷综合| 成人淫片在线看| 国产精品久久免费| 浪潮色综合久久天堂| 亚洲男人av在线| av黄色在线观看| 久久69精品久久久久久国产越南| 国产偷倩在线播放| 97成人精品区在线播放| 99欧美精品| 成人区精品一区二区| 最近国产精品视频| 在线精品亚洲一区二区| 亚洲性图久久| 亚洲国产精品毛片av不卡在线| 另类综合日韩欧美亚洲| 欧美做受高潮中文字幕| 国产欧美一区二区精品性| 超碰在线国产97| 色综合中文字幕| av官网在线观看| 亚洲人a成www在线影院| 1024在线播放| 国产999在线观看| 亚洲精品v亚洲精品v日韩精品| 久久精品欧美| 欧美黄色aaaa| 50路60路老熟妇啪啪| 国产麻豆精品95视频| 国产特黄级aaaaa片免| 亚洲视频中文字幕| 草莓视频18免费观看| 精品卡一卡二卡三卡四在线| av中文字幕在线| 66m—66摸成人免费视频| av在线播放一区二区| 欧美日韩精品中文字幕一区二区| 中文精品电影| 嫩草影院国产精品| 91在线观看免费视频| 久久久久久福利| 欧美裸体bbwbbwbbw| 国外av在线| 97视频人免费观看| 亚洲网一区二区三区| 一区二区不卡在线| 日日夜夜精品视频免费| 四虎国产精品免费| 国产欧美一区二区三区在线老狼 | 舔着乳尖日韩一区| 精品黑人一区二区三区国语馆| 亚洲免费小视频| 91九色在线看| 97人人模人人爽人人喊38tv| 久久精品高清| 色综合天天色综合| 久久精品夜夜夜夜久久| 91精品国产乱码在线观看| 欧美α欧美αv大片| 黄色在线视频网站| 国产一区二区在线免费视频| 欧洲杯什么时候开赛| 亚洲自偷自拍熟女另类| 99精品桃花视频在线观看| 国产精品18p| 精品对白一区国产伦| 色呦呦呦在线观看| 99国产超薄丝袜足j在线观看| 围产精品久久久久久久| 一区二区在线免费看| 国产精品久久久久久久久搜平片| 中文字幕av网站| 在线观看国产精品日韩av| 精品日本视频| 午夜精品视频在线观看一区二区| 日韩高清一区二区| 女人裸体性做爰全过| 欧美高清精品3d| 黄色网页在线播放| 97超级在线观看免费高清完整版电视剧| 午夜国产一区二区| 1314成人网| 亚洲国产日产av| 天天色综合av| 日本不卡高字幕在线2019| 久久99免费视频| 在线看的黄色网址| 亚洲色图视频网站| 女人18毛片水真多18精品| 97视频在线观看视频免费视频| 香蕉国产成人午夜av影院| 成人黄色一区二区| 一区在线播放视频| 亚洲国产www| 欧美亚洲激情视频| 欧美综合另类| 永久免费黄色片| 午夜视频一区二区| 毛片免费在线观看| 国产精品一区=区| 最新国产精品久久久| 亚洲熟女乱综合一区二区三区| 色综合久久久久| 黄色网址在线免费播放| 国产美女99p| 老鸭窝毛片一区二区三区| 性猛交娇小69hd| 91精品国产高清一区二区三区蜜臀 | 91亚洲精品一区二区乱码| 欧美日韩 一区二区三区| 久久激情五月丁香伊人| 国产香蕉精品| 91视频免费版污| 一区二区三区在线免费播放| 日产精品久久久久久久性色| 国产精品日韩精品| 雨宫琴音一区二区在线| 国产又粗又猛又爽又黄av| 日韩欧美在线综合网| 不卡一二三区| 2022中文字幕| 国产日韩欧美一区二区三区乱码| 国产高清视频免费| 国产精品久久久久一区二区| 伊人成人在线视频| 色偷偷男人天堂| 亚洲国产高清高潮精品美女| 久久久久久久性潮|