React Native -- 与原生交互(iOS)

作者: PetitBread | 来源:发表于2018-08-24 14:33 被阅读13次

    如果没接触过 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>
            );
        }
    
    

    相关文章

      网友评论

        本文标题:React Native -- 与原生交互(iOS)

        本文链接:https://www.haomeiwen.com/subject/ftdmiftx.html