不一樣於Hybrid ap,React Native裏面沒有webview
,iOS7中加入了JavaScriptCore.framework
框架,而RN正是用JavascriptCore執行js代碼的。html
須要安裝Watchman
Flow
Node
環境,推薦使用Homebrew
,注意Xcode版本不能低於7.0java
國內須要換源node
1 npm config set registry https://registry.npm.taobao.org
2 npm config set disturl https://npm.taobao.org/dist
執行如下兩條命令安裝全局npm環境和初始化工程RNDEMOreact
$ sudo npm install -g react-native-cli
$ react-native init RNDemo
cd到工程根目錄中用npm start(若是開啓了自動啓動調試服務器則不須要)啓動服務,而後運行工程web
1.拷貝node_modules環境到工程中npm
2.將須要的.xcodeproj文件添加到工程中react-native
3.點擊 項目>Targets>Bulid Phases>Link Binary With Libraries添加對應的靜態庫數組
4.點擊 項目>Targets>Bulid Settings>Search Paths>Header Search Paths註冊React.xcodeproj文件路徑xcode
5.由於靜態庫裏面可能有Category 因此須要在項目>Targets>Build Settings -> other linker flags 中加入-ObjC或者-all_load服務器
RN能用JS方便地調用官方封裝的組件來加大開發效率,可是一些個性化或者js不太方便的東西仍是須要native實現,因而須要native提供一些原生組件來完善。這主要分爲兩類,Module類和View類
兩種類都須要實現 RCT_EXPORT_MODULE(js_name) 協議宏,js_name是js調用該類名稱,缺省狀況下截取類所在文件名,一個類所在文件被引用時,系統會調用其+(void)load函數,當RCT_EXPORT_MODULE()所在文件被引用時,系統調用load 函數,函數裏簡單的調用RCTRegisterModule(self) 把本身註冊到一個全局數組RCTModuleClasses,這樣系統中導出的類都會自動註冊到這個全局變量數組裏
void RCTRegisterModule(Class moduleClass)
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
RCTModuleClasses = [NSMutableArray new];
});
RCTAssert([moduleClass conformsToProtocol:@protocol(RCTBridgeModule)], @"%@ does not conform to the RCTBridgeModule protocol", moduleClass);
// Register module
[RCTModuleClasses addObject:moduleClass];
}
屬性導出
RN能夠向Native傳遞多種參數,能夠以這些支持的類型傳遞數據native組件用EXPORT_VIEW_PROPERTY(<#name#>, <#type#>)
來導出類的屬性,js傳遞數據會調用相應的set方法,native能夠在set方法裏面作些邏輯和數據處理。支持字符串NSString,NSArray數組,基本數據類型,NSnumeber,NSDictionary字典等,自定義類型,並在RCTCovert中,重定義了以下幾種數據類型來處理一些泛型
typedef NSArray NSArrayArray __deprecated_msg("Use NSArray");
typedef NSArray NSStringArray __deprecated_msg("Use NSArray");
typedef NSArray NSStringArrayArray __deprecated_msg("Use NSArray<NSArray *>");
typedef NSArray NSDictionaryArray __deprecated_msg("Use NSArray");
typedef NSArray NSURLArray __deprecated_msg("Use NSArray");
typedef NSArray RCTFileURLArray __deprecated_msg("Use NSArray");
typedef NSArray NSNumberArray __deprecated_msg("Use NSArray");
typedef NSArray UIColorArray __deprecated_msg("Use NSArray");
枚舉類型用RCT_ENUM_CONVERTER(type, values, default, getter)導出 例如:
RCT_ENUM_CONVERTER(UIActivityIndicatorViewStyle, (@{
@"large": @(UIActivityIndicatorViewStyleWhiteLarge),
@"small": @(UIActivityIndicatorViewStyleWhite),
}), UIActivityIndicatorViewStyleWhiteLarge, integerValue)
values爲字典類型,default在js傳遞數據爲空時候使用
RCT_EXPORT_METHOD(<#method#>)可導出方法,js經過註冊到全局數組RCTModuleClasses中的實例來調用方法
RCT_EXPORT_METHOD(getCurrentVersion:(RCTResponseSenderBlock)callback)
{
NSString *events = [self appVersion];
callback(@[events]);
}
React Native 在一個單獨的串行 GCD 隊列中調用 native 模塊方法,若是 native 模塊須要調用 main-thread-only iOS API例如刷新UI,push viewController 應該在主隊列操做:
-(void)whatYouWantTodo{
dispatch_async(dispatch_get_main_queue(), ^{
coding......
}
}
對應屬性導出,native也能夠向js傳遞數據,RCTBridgeMethod中定義了一個block typedef void (^RCTResponseSenderBlock)(NSArray *response);
用來返回數據給js。
RCTEventDispatcher類中定義了一些事件處理方法
例如Native 模塊能夠在不被直接調用的狀況下向 JavaScript 發送事件信號
- (void)calendarEventReminderReceived:(NSNotification *)notification
{
NSString *eventName = notification.userInfo[@"name"];
[self.bridge.eventDispatcher sendAppEventWithName:@"EventReminder"
body:@{@"name": eventName}];
}
@end
JavaScript 代碼能夠訂閱這些事件:
var subscription = DeviceEventEmitter.addListener(
'EventReminder',
(reminder) => console.log(reminder.name)
);
tips:js須要移除訂閱事件
subscription.remove();
5、簡單提提JavaScriptCore
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
//網頁加載完成調用此方法
//首先建立JSContext 對象(此處經過當前webView的鍵獲取到jscontext)
JSContext *context=[webView valueForKeyPath: @"documentView.webView.mainFrame.javaScriptContext"];
NSString *alertJS=@"alert('超哥你好,大河向東流')"; //準備執行的js代碼
[context evaluateScript:alertJS];//經過oc方法調用js的alert
}
效果以下:
用[JSContext currentContext]
JSContext *context1 = [[JSContext alloc] init];
context1[@"callback"] = ^{
JSValue *object = [JSValue valueWithNewObjectInContext:[JSContext currentContext]];
object[@"one"] = @(1);
object[@"two"] = @(2);
return object;
};
JSValue內存泄漏
JS中對象爲弱類型,OC中爲強類型直接保存會內存泄漏
- (void)setOnClickHandler:(JSValue *)handler
{
_onClickHandler = [JSManagedValue managedValueWithValue:handler];
[_context.virtualMachine addManagedReference:_onClickHandler
withOwner:self]
}
資料參考:
知識淺薄,若有錯漏請指正。