在RN开发中不可避免的遇到需要Native扩展的情况,比如我们需要使用React-Native并没有封装的原生功能,其次我们可能需要使用到多线程和性能要求比较高的功能,此时,往往我们需要进行Native扩展。
模块和方法的定义
一个普通的Objective-C类和方法是不会被系统处理成模块进而被调用,模块运行时向系统注册,同时告诉系统什么属性和方法可以被JavaScript调用,模块类必须遵守RCTBridgeModule协议,该协议中定义了作为模块需要的属性和方法以及宏定义。
导出模块宏:
RCT_EXPORT_MODULE
导出模块方法宏:
RCT_EXPORT_METHOD
eg:导出模块类
Objective-C代码
#import <Foundation/Foundation.h>
#import "RCTBridgeModule.h"
@interface JJSRCTModule : NSObject<RCTBridgeModule>
@end
#import "JJSRCTModule.h"
#import <UIKit/UIKit.h>
@implementation JJSRCTModule
//导出模块
RCT_EXPORT_MODULE()
导出模块方法 只有导出告诉系统我们才可以在JavaScript中使用模块方法
RCT_EXPORT_METHOD(testFunc:(NSString*)str1 index:(NSString*)str2){
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"test" message:@"test" delegate:nil cancelButtonTitle:str1 otherButtonTitles:str2, nil];
[alertView show];
});
}
@end
JavaScript使用代码:
//导入模块 JJSRCTModule就是添加的模块 注意如果模块名前缀包含了RCT,会被格式化去除
var myModule = require('NativeModules').JJSRCTModule;
myModule.testFunc("否","是");
回调函数
React-Native中允许JavaScript在调用扩展方法中使用回调函数,回调block的定义:
typedef void (^RCTResponseSenderBlock)(NSArray *respone)
//接受多个参数,传递的参数和接受的参数要一一顺序对应
typedef void (^RCTResponseErrorBlock)(NSError* error)
//接受错误参数的回调函数
eg:
Objective-C代码
RCT_EXPORT_METHOD(testCallback:(CTRResponseSenderBlock) callBack ){
if(callBack){
callBack(@[@"hello,",@"world"]);
}
}
JavaScript代码
myModule.testCallback((str1,str2)=>{
AlertIOS.alert(str1 + str2);
});
导出常量
React-Native允许暴露一些常量给JavaScript模块使用,主要通过
-(NSDictionary*)constansToExport方法导出,需要注意的是常量导出在框架初始化期间导出到模块配置表中,不能在运行时在对导出的字典修改,因为这是无效的。
eg:
Objective-C代码
-(NSDictionary*)constansToExport{
return @{@"version":@"1.0.1"};
}
JavaScript代码
alert(myModule.version);
事件
React-Native实现了Native到JavaScript一种消息传递机制,Native可通过RCTEventDispatcher向JavaScript端的EventEmitter模块发送事件消息,由EventEmitter模块通知该事件的订阅者来响应事件的响应。
eg:
Objective-C代码
-(id)init{
if (self = [super init]) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(enterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
}
return self;
}
-(void)enterBackground:(NSNotification*)notice{
NSLog(@"enterBackground");
//注意的坑:在使用eventDispatcher时候必须导入CRTEventDispatcher.h文件不然编译不了
[self.bridge.eventDispatcher sendAppEventWithName:@"testNotice" body:@{@"key":@"Value"}];
}
JavaScript代码
var subscription = NativeAppEventEmitter.addListener("testNotice",(reminder)=>{ console.log("get Message");});