不一样于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]
}
资料参考:
知识浅薄,若有错漏请指正。