前言
无论是 flutter 还是 react-native,在开发过程中都避免不了与原生端的交互,因此对其了解是必要的,这里主要介绍 react-native与原生端的交互
react-native向ios端通信
ios端实现
原生需要创建一个继承自NSObject的类(模块),且遵循 RCTBridgeModule 协议
#import <React/RCTBridgeModule.h>
@interface AppEventMoudle : NSObject <RCTBridgeModule>
@end
在AppEventMoudle.m文件件中需要导出改模块, 并将创建的方法导出
#import "AppEventMoudle.h"
@implementation AppEventMoudle
// 导出桥接模块, 参数传空或者当前class的类名
// 参数若为空, 默认模块名为当前class类名即AppEventMoudle
RCT_EXPORT_MODULE(AppEventMoudle);
//无参方法
RCT_EXPORT_METHOD(open) {
}
// 带有参数
RCT_EXPORT_METHOD(OpenView:(NSDictionary *)params){
// 因为是显示页面,所以让原生接口运行在主线程
dispatch_async(dispatch_get_main_queue(), ^{
// 在这里可以写需要原生处理的UI或者逻辑
NSLog(@"params = %@", params);
});
}
/// 带有回调
RCT_EXPORT_METHOD(OpenView:(NSDictionary *)params, callback:(RCTResponseSenderBlock)callback){
if (callback) {
callback(@[params]);
}
}
注意:
桥接到Javascript的方法返回值类型必须是void
React Native的桥接操作是异步的,在queue里面异步执行,所以如果要返回结果给Javascript,就必须通过回调或者触发事件来进行
这里的回调对应于iOS端就是通过block来回调的
RCTBridge
RCTBridge可以说是一个封装类,封装了RCTCxxBridge
我们先看这个文件提供的一些变量和方法
RCTModuleClasses: 主要储存的是我们注册的module, 所有用宏RCT_EXPORT_MODULE()注册的module都会存入这个变量.
RCTGetModuleClasses: 获取RCTModuleClasses里面所有注册的module类
RCTBridgeModuleNameForClass: 从一个类获取这个类的名字
RCTVerifyAllModulesExported: 验证我们所写的所有遵守RCTBridgeModule协议的类是否都在我们的管理中
RCTResponseSenderBlock
typedef void (^RCTResponseSenderBlock)(NSArray *response);
RCTResponseSenderBlock是RCTBridgeModule里面提供的block
这个block接受一个数组参数, 代表原生方法的返回结果
线程问题
js代码的执行是在js线程里面,原生模块的执行默认是在一个串行的queue里面异步执行的
对于原生模块的执行来说,默认一个串行的queue是不够的,我们有时候需要指定模块所有任务执行所在的queue
RCT_EXPORT_METHOD(OpenView:(NSDictionary *)params){
// 因为是显示页面,所以让原生接口运行在主线程
dispatch_async(dispatch_get_main_queue(), ^{
// 在这里可以写需要原生处理的UI或者逻辑
NSLog(@"params = %@", params);
});
}
react-native端实现
从这里,通过 NativeModules 中介来调用原生中的方法
import {NativeModules} from 'react-native';
export default class App extends Component{
turnOn = () => {
//直接调用导出模块的相应方法
NativeModules.AppEventMoudle.open();
}
}
ios向react-native端通信
与上面的类似,这里面简介一下,只不过是通过 RCTEventEmitter 来通信
ios原生端
先导入下面框架,继承自 RCTEventEmitter,且遵循 RCTBridgeModule 协议
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
@interface PushNotificationEventEmitter : RCTEventEmitter<RCTBridgeModule>
@end
.m 文件
@implementation PushNotificationEventEmitter
//模块化导出,如果没名字,就导入当前的class类名
RCT_EXPORT_MODULE();
-(void)operateReactNative {
//直接发送消息即可,body可以传递数组和字典等比较基础的类型
[self sendEventWithName:@"operateReactNative" body:nil];
}
@end
react-native端
import {NativeAppEventEmitter} from 'react-native';
export default class App extends Component{
listenByReactNative = () => {
//直接调用导出模块的相应方法
this.webViewListener = NativeAppEventEmitter.addListener('operateReactNative', message => {
我是原生端传递过来的信息
})
}
}