React Native -- 与原生交互(iOS)
2018-08-24 本文已影响13人
PetitBread
如果没接触过 React Native的可以先去看这篇文章,把基本环境搭建好,本篇说一下 RN 与 原生的相互交互与传参( 这里只讲iOS这一块)
功能
-
RN 点击按钮触发 原生 方法,RN 带参传递给原生
-
原生 调用 RN 方法,原生 带参 传递给 RN 端
示例代码说明
Native 端
1.首先需要调用的原生方法需要继承类RCTEventEmitter
,然后实现 RCTBridgeModule
协议
2.类实现中需要添加 RCT_EXPORT_MODULE()
的宏
3.通过 RCT_EXPORT_METHOD()
宏 来实现需要导出 javascript
的方法
看一下 Native 端的类文件
RNMethodTool.h
#import <React/RCTEventEmitter.h>
#import <React/RCTBridge.h>
@interface RNMethodTool : RCTEventEmitter<RCTBridgeModule>
+(void)emitMethod;
// RN那边做了监听,这个就是调用 RN 方法,弹出 RN 系统提示框
@end
这里引入 RCTBridge.h
之类的文件可能会报错file not found
,编译一下就 OK 了,不用管。
RNMethodTool.m
#import "RNMethodTool.h"
#import "AppDelegate.h"
@implementation RNMethodTool
//这个宏必写的,不谢的话 RN 那边会找不到该类
RCT_EXPORT_MODULE()
//这个方法也是必须实现的
-(NSArray<NSString *>*)supportedEvents
{
return @[@"EventReminder"];
//EventReminder 是监听的标识,类似 iOS 发通知 需要一个标识去识别,通过这个标识发送通知调用 RN方法
}
// RCT_EXPORT_METHOD( xxx) 暴露给 RN 调用的方法写这里面, xxx 是调用方法
RCT_EXPORT_METHOD(pp_startObserving)
{
//里面就是做一些原生操作了,比如跳转,打开相册,相机之类
//这里是加个通知,其他原生类里通过发送通知来调用 alertRNInfo 方法,就是实现发通知给 RN 的功能方法
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(alertRNInfo:) name:@"pp123" object:nil];
}
RCT_EXPORT_METHOD(doSomething:(NSString *)string)
{
//这也是暴露给 RN 的方法,弹出系统框,string 是 RN给过来的参数
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"我是iOS系统框 RN 调用 原生方法" message:string preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleDefault handler:nil];
[alertController addAction:cancelAction];
[alertController addAction:okAction];
AppDelegate *delegate = (AppDelegate *)([UIApplication sharedApplication].delegate);
[delegate.window.rootViewController presentViewController:alertController animated:YES completion:nil];
});
}
-(void)alertRNInfo:(NSNotification *)noti
{
dispatch_async(dispatch_get_main_queue(), ^{
//这是核心方法, EventReminder 是标识,在上面的数组 supportedEvents 方法里也要加入, body 是 传给 RN 的参数
[self sendEventWithName:@"EventReminder" body:@{@"name":@"pp"}];
});
}
//这个就是暴露给其他原生类的方法了
+(void)emitMethod
{
[[NSNotificationCenter defaultCenter]postNotificationName:@"pp123" object:nil];
}
//我这里在 `AppDelegate.m`类调用来测试是否可以成功调用
/*dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(6 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[RNMethodTool emitMethod];
});
*/
@end
要注意的点
-
如果没有
RCT_EXPORT_MODULE
这个宏的话,会报错,也就是 RN 找不到这个 module , 因为没有用这个宏导出暴露给 RN
-
supportedEvents
如果没有实现这个方法,你会发现每次 run-ios 模拟器一打开就会闪退,而且没有错误提示 -
supportedEvents
这个数组方法里如果不加入标识,点击是没反应的,这里是 EventReminder ,可以自己命名
JS端:
1.需要引用 NativeModules
模块
2.通过 NativeModules.xxx
获取 Native 的类,xxx 为 Native 的类名
3.上一步获取到的 Native 类,调用 Native 中导出的方法
示例代码说明
//先导入这俩个组件
import {NativeEventEmitter,NativeModules} from 'react-native';
//初始化, RNMethodTool 就是原生类的名字
var NativeBridge = NativeModules.RNMethodTool;
const NativeModule = new NativeEventEmitter(NativeModules.RNMethodTool)
//在页面加载完成之后,这里类似于 iOS 的 viewDidLoad
componentDidMount() {
NativeBridge.pp_startObserving(); //添加监听,作用参考原生里面的方法
//核心方法,通过 EventReminder 这个标识监听 原生发过来的通知,收到之后就调用里面的方法,data 是传过来的参数
NativeModule.addListener('EventReminder',(data)=>{
var dic = JSON.stringify(data);
alert('我是 RN 弹框,原生 调用 RN方法' + ' ' + '原生带过来的参数'+ dic);
})
}
//点击 RN 按钮调用原生方法,比如
render() {
return (
<TouchableHighlight onPress={ ()=>NativeBridge.doSomething('RN传递的参数')}>
<Text style={styles.text}>
点击
</Text>
</TouchableHighlight>
);
}