基於 JLRoute 實現的模組化示例,包括連結跳轉原生頁面、WebView頁面和ReactNative頁面 ?
模組化已經成為調劑龐大專案結構的一劑良藥,對專案的開發、維護和後續的擴充套件的好處已經不言而喻。
? 要求
- iOS 8.0+
- Xcode 7.0+
? 安裝方法
安裝
在 iOS, 你需要在 Podfile 中新增.
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'
use_frameworks!
pod 'JLRoutes', '~> 2.0.1'
# 'node_modules'目錄一般位於根目錄中
# 但是如果你的結構不同,那你就要根據實際路徑修改下面的`:path`
pod 'React', :path => './node_modules/react-native', :subspecs => [
'Core',
'RCTText',
'RCTNetwork',
'RCTWebSocket', # 這個模組是用於除錯功能的
# 在這裡繼續新增你所需要的模組
]
# 如果你的RN版本 >= 0.42.0,請加入下面這行
pod "Yoga", :path => "./node_modules/react-native/ReactCommon/yoga"
複製程式碼
啟動 ReactNative 環境
1.修改專案ModuleARNPageViewController.m IP 跳轉地址
2.進入專案所在目錄,執行(首次執行需要 npm install)
npm start
複製程式碼
? JLRoutes的工作流程和原理
單一的Scheme註冊過程:
1.呼叫註冊方法(使用者註冊routePattern,預設優先順序0)
- (void)addRoute:(NSString *)routePattern handler:(BOOL (^__nullable)(NSDictionary<NSString *, id> *parameters))handlerBlock;
複製程式碼
2.路由解析(這些解析跟我們設定路由的規則有直接關係)
(1)判斷介面URL是否設定可選性URL並將對應的URL封裝成JLRRouteDefinition物件
(2)將JLRRouteDefinition物件裝載進一個可變陣列,記憶體保留了所有的物件!!
(JLRRouteDefinition物件包括有路徑,引數解析,block等資訊)
單一的Scheme呼叫過程:
1.呼叫URL
+ (BOOL)routeURL:(NSURL *)URL
複製程式碼
2.解析URL,將引數,路由資訊封裝成JLRRouteRequest物件
- (instancetype)initWithURL:(NSURL *)URL alwaysTreatsHostAsPathComponent:(BOOL)alwaysTreatsHostAsPathComponent
複製程式碼
3.給JLrouteRequest物件和路由陣列裡的JLRRouteDefinition物件作比對,並且返回JLRRouteResponse 物件抽出引數和URL在陣列裡
JLRRouteResponse *response = [route routeResponseForRequest:request decodePlusSymbols:shouldDecodePlusSymbols];
複製程式碼
4.呼叫JLRRouteResponse 物件裡面的回撥方法
[route callHandlerBlockWithParameters:finalParameters];
複製程式碼
JLRoutes的URL註冊規則:
1.普通註冊
JLRoutes *routes = [JLRoutes globalRoutes];
[routes addRoute:@"/user/view/:userID" handler:^BOOL(NSDictionary *parameters) {
NSString *userID = parameters[@"userID"]; // defined in the route by specifying ":userID"
// present UI for viewing user with ID 'userID'
return YES; // return YES to say we have handled the route
}];
複製程式碼
URL裡,分號表示這個是引數
另外一種註冊方式,下標註冊法
JLRoutes.globalRoutes[@"/route/:param"] = ^BOOL(NSDictionary *parameters) {
// ...
};
複製程式碼
如何按照以上的方式註冊,在任何時刻(包括在其它的APP)你都可以呼叫這個URL。
NSURL *viewUserURL = [NSURL URLWithString:@"myapp://user/view/joeldev"];
[[UIApplication sharedApplication] openURL:viewUserURL];
複製程式碼
在這個例子中,在parmameters字典裡面的userID會傳給block,它是一個鍵值對。”userID”: “joeldev”。給UI層或者任何需要它的地方用的。
字典引數:
字典引數總包括至少一下3個鍵:
{
"JLRouteURL": "(the NSURL that caused this block to be fired)",
"JLRoutePattern": "(the actual route pattern string)",
"JLRouteScheme": "(the route scheme, defaults to JLRoutesGlobalRoutesScheme)"
}
複製程式碼
處理Block
你會發現,每個註冊的block都會返回一個YES。這個值,如果你返回NO,JLRoutes會跳過這個匹配,然後繼續去匹配其它的。
如果你的block設定成nil,它會預設返回YES。
2.複雜註冊
[[JLRoutes globalRoutes] addRoute:@"/:object/:action/:primaryKey" handler:^BOOL(NSDictionary *parameters) {
NSString *object = parameters[@"object"];
NSString *action = parameters[@"action"];
NSString *primaryKey = parameters[@"primaryKey"];
// stuff
return YES;
}];
複製程式碼
這個地址會被匹配很多URL,如/user/view/joeldev or /post/edit/123。這些URL上的是引數。
NSURL *editPost = [NSURL URLWithString:@"myapp://post/edit/123?debug=true&foo=bar"];
[[UIApplication sharedApplication] openURL:editPost];
複製程式碼
這時,pramater字典就會是以下這樣的(傳參)
{
"object": "post",
"action": "edit",
"primaryKey": "123",
"debug": "true",
"foo": "bar",
"JLRouteURL": "myapp://post/edit/123?debug=true&foo=bar",
"JLRoutePattern": "/:object/:action/:primaryKey",
"JLRouteScheme": "JLRoutesGlobalRoutesScheme"
}
複製程式碼
3.Scheme(有沒有多型的感覺)
JLRoutes支援用指定的URL scheme來建立路由。相同的scheme才能被匹配。預設地,所有的URL會設定進global scheme。
[[JLRoutes globalRoutes] addRoute:@"/foo" handler:^BOOL(NSDictionary *parameters) {
// This block is called if the scheme is not 'thing' or 'stuff' (see below)
return YES;
}];
[[JLRoutes routesForScheme:@"thing"] addRoute:@"/foo" handler:^BOOL(NSDictionary *parameters) {
// This block is called for thing://foo
return YES;
}];
[[JLRoutes routesForScheme:@"stuff"] addRoute:@"/foo" handler:^BOOL(NSDictionary *parameters) {
// This block is called for stuff://foo
return YES;
}];
複製程式碼
如果你呼叫的使用,是這樣呼叫的
[[JLRoutes globalRoutes] addRoute:@"/global" handler:^BOOL(NSDictionary *parameters) {
return YES;
}];
複製程式碼
它只會呼叫global scheme的對應的URL。不會呼叫ting scheme裡面對應的URL。
當然,你可以設定,如果指定的scheme沒有這個URL,去查詢global scheme 有沒有。你需要設定一個屬性。
[JLRoutes routesForScheme:@"thing"].shouldFallbackToGlobalRoutes = YES;
複製程式碼
3.萬用字元的設定URL的方式
萬用字元為:*
萬用字元符後面所有的URL上的引數都會以一個陣列儲存在parameters字典裡面的JLRouteWildcardComponentsKey對應的value裡。
例如,如果你註冊URL如下:
[[JLRoutes globalRoutes] addRoute:@"/wildcard/*" handler:^BOOL(NSDictionary *parameters) {
NSArray *pathComponents = parameters[JLRouteWildcardComponentsKey];
if ([pathComponents count] > 0 && [pathComponents[0] isEqualToString:@"joker"]) {
// the route matched; do stuff
return YES;
}
// not interested unless the joker's in it
return NO;
}];
複製程式碼
如果呼叫的URL開始是/wildcard,這個路由就可能被觸發!!如果第一個引數是joker,就被觸發,如果不是,就被拒絕觸發。。。
4.選擇性路由
如果路由地址設定樣式有括號,如:/the(/foo/:a)(/bar/:b),其實它代表的URL有如下:
/the/foo/:a/bar/:b
/the/foo/:a
/the/bar/:b
/the
複製程式碼
5.查詢Routes
下面的方式,你可以檢視Routes裡所有註冊的URL Routes。
/// All registered routes, keyed by scheme
+ (NSDictionary <NSString *, NSArray <JLRRouteDefinition *> *> *)allRoutes;
/// Return all registered routes in the receiving scheme namespace.
- (NSArray <JLRRouteDefinition *> *)routes;
複製程式碼
自定義路由解析 如果你想自己定製一個路由編輯,你可以繼承JLRouteDefinition並且用 addRoute:方法去新增你自定義類的物件。
? 調研來源
JLRoutes:github.com/joeldev/JLR…
JLRoutes資料部落格:www.varsiri.com/archives/30…
? 聯絡
- 微信 : WhatsXie
- 郵件 : ReverseScale@iCloud.com
- 部落格 : reversescale.github.io
- 原始碼 : github.com/ReverseScal…