集成 RN 的目的
代碼熱更新
多端代碼復(fù)用
團隊考慮集成 RN 主要是為了代碼熱更新。
相對于原生開發(fā),使用 RN,初期成本可能會有些高。
如果團隊人員足夠,而且不存在審核方面的問題,不建議在現(xiàn)有項目里面集成 RN。
存在的問題
由于項目已使用原生代碼開發(fā)了完整的功能,集成 RN 大多是新模塊的開發(fā),所以就涉及到原生與 RN 間相互跳轉(zhuǎn)傳參。RN 模塊自身使用 StackNavigator 可以很好的進行導(dǎo)航管理;Native 跳轉(zhuǎn) RN,主要是提供 View Controller 作為容器,承載 RCTRootView;關(guān)鍵在于RN 跳轉(zhuǎn) Native,不可能對每一個對應(yīng)的跳轉(zhuǎn)都寫一次 Bridge 方法??紤]到這里,就想到了路由。以路由的方式,可以方便的對項目進行解耦,統(tǒng)一處理 Native 與 RN 間的跳轉(zhuǎn)。
Demo中選用了 JLRoutes 方案。
集成步驟
1、定義跳轉(zhuǎn)協(xié)議
在 plist 中加入下列代碼
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>CCDemo</string>
</array>
</dict>
</array>
這里,使用 CCDemo 作為協(xié)議,使用 CCDemo:// 就可以跳轉(zhuǎn)到應(yīng)用內(nèi)了。
2、定義跳轉(zhuǎn)規(guī)則
這里新建一個 RouterManager 統(tǒng)一處理 router 相關(guān)。這里也建議大家這樣做,如果以后要修改或新增跳轉(zhuǎn)協(xié)議類型(多Target),會簡單得多。
CCRouterManager
- (void)setupRouterRule {
/// vc from code
[[JLRoutes globalRoutes] addRoute:@"/NavPush/:controller" handler:^BOOL(NSDictionary<NSString *,NSString *> * _Nonnull parameters) {
UIViewController *v = [[NSClassFromString(parameters[@"controller"]) alloc] init];
[self paramToVc:v param:parameters];
[[AppDelegate sharedDelegate].currentVC pushViewController:v animated:YES];
return YES;
}];
}
- (void)paramToVc:(UIViewController *) v param:(NSDictionary<NSString *,NSString *> *)parameters {
unsigned int outCount = 0;
objc_property_t * properties = class_copyPropertyList(v.class , &outCount);
for (int i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
NSString *key = [NSString stringWithUTF8String:property_getName(property)];
NSString *param = parameters[key];
if (param != nil) {
[v setValue:param forKey:key];
}
}
}
這里只實現(xiàn)了從代碼中加載 VC,從 Xib 或 StoryBoard 加載可以自行實現(xiàn)。
AppDelegate
static AppDelegate *sInstance = nil;
+ (instancetype)sharedDelegate {
if (sInstance == nil) {
sInstance = [[AppDelegate alloc] init];
}
return sInstance;
}
- (id)init {
if (self = [super init]) {
sInstance = self;
}
return self;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[CCRouterManager sharedInstance] setupRouterRule];
return YES;
}
- (UINavigationController *)currentVC
{
return (UINavigationController *)self.window.rootViewController;
}
3、handle url
在 AppDelegate 中加入如下代碼
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
if ([url.absoluteString containsString:@"CCDemo://"]) {
return [[CCRouterManager sharedInstance] canRouteURL:url];
}
return YES;
}
到這里,router 部分就完成了,現(xiàn)在可以通過
NSDictionary *para = @{
@"labelText" : @"CCOneController-labelText",
};
[[CCRouterManager sharedInstance] pushToVC:@"CCOneController" paramters:para];
來實現(xiàn)跳轉(zhuǎn)了。
demo 地址 tag: router
與原生頁面相互跳轉(zhuǎn)見下節(jié) iOS原生項目集成 React Native 一 導(dǎo)航