React Native 调用 Native 模块

  1. 声明一个类,必须实现<RCTBridgeModule> 协议

  2. .m文件中实现宏定义RCT_EXPORT_MODULE(),当它加载的时候,会自动注册

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // js_name 就是react native 获取类时所对应的名称,
    // 即 NativeModules.js_name
    // 传空的话,名称就是类名字
    // #define RCT_EXPORT_MODULE(js_name)
    // .m 文件
    RCT_EXPORT_MODULE(Test);
    // js 文件
    import {NativeModules} from 'react-native';
    var Test = NativeModules.Test;
  3. 调用方法,js调用OC的方法

    • 需要另外一个宏RCT_EXPORT_METHOD(method),js 中 使用.来调用
    • 方法返回值类型必须为void
    • 传参类型

      • string: NSString
      • number: 基本类型
      • boolean
      • array
      • object: NSDictionary, key为string,value是列表中的类型
      • function: RCTResponseSenderBlock
      1
      2
      3
      4
      5
      6
      7
      8
      // .m 文件
      RCT_EXPORT_METHOD(print:(NSString *)text)
      {
      NSLog(@"---------%@", text);
      }
      // js文件
      Test.print('Hello World!');
  4. 回调函数,js中的参数经过OC方法的处理,结果再返回给js

    • RCTResponseSenderBlock 唯一参数,数组
    • 第一个元素一般为错误对象,第二个元素才是返回结果

      1
      2
      3
      4
      5
      6
      7
      8
      9
      // .m
      RCT_EXPORT_METHOD(add:(NSInteger)numA andNumB:(NSInteger)numB result:(RCTResponseSenderBlock)callback) {
      callback(@[[NSNull null], @(numA + numB)]);
      }
      // js
      Test.add(1, 2, (error, result)=>{
      alert('1 + 2 =' + result);
      });
  5. 设定原生模块所处线程

    • 实现- (dispatch_queue_t) methodQueue,即原生模块中的所有方法都会在methodQueue中执行
    • 也可以RCT_EXPORT_METHOD()方法内部开辟分线程,让一些费时的操作在分线程中执行

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      RCT_EXPORT_METHOD(doSomethingExpensive:(NSString *)parma callback:(RCTResponseSenderBlock)callback) {
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
      // 执行长时间的操作
      // callback视情况 1, 2 位置都可以
      // 1. callback(@[]);
      });
      // 2. callback(@[]);
      }
  6. 导出常量

    • 原生模块导出一些常量,让js可以随时访问,并且运行期间不会改变
    • 方法名必须是- (NSDictionary *)constantsToExport

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      // .m
      - (NSDictionary *)constantsToExport
      {
      return @{
      @"firstDayOfWeek": @"Monday"
      };
      }
      // js
      alert(Test.firstDayOfWeek);
  7. 发送事件

    1. 类需要继承RCTEventEmitter

      1
      2
      3
      4
      #import "RCTEventEmitter.h"
      #import "RCTBridgeModule.h"
      @interface MyModule : RCTEventEmitter <RCTBridgeModule>
    2. 实现supportedEvents方法,设置发送事件的名称

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      // 注册该类,对外名称为RN,
      RCT_EXPORT_MODULE(RN);
      // 设置可以发送的事件名称数组
      - (NSArray<NSString *> *)supportedEvents
      {
      return @[@"textChange"];
      }
      - (void)changeText:(NSString *)text
      {
      self.text = text;
      // 发送事件
      [self sendEventWithName:@"textChange" body:@{
      @"text": self.text
      }];
      }
    3. js文件中

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      import { NativeModules, NativeEventEmitter } from 'react-native'
      // 获取组件RN
      var RN = NativeModules.RN;
      const RNEvent = new NativeEventEmitter(RN);
      var subscription = RNEvent.addListener(
      'textChange',
      (result) => alert(result.text)
      );

参考链接:
官网
中文官网
发送事件