一、从React Native中调用原生方法(原生模块)
原生模块是JS中也可以使用的Objective-C类。一般来说这样的每一个模块的实例都是在每一次通过JS bridge通信时创建的。他们可以导出任意的函数和常量给React Native。相关细节可以参阅这篇文章。
在React Native中,一个“原生模块”就是一个实现了“RCTBridgeModule”协议的Objective-C类,其中RCT是ReaCT的缩写。
// CalendarManager.h #import <React/RCTBridgeModule.h> #import <React/RCTLog.h> @interface CalendarManager : NSObject <RCTBridgeModule> @end
  为了实现RCTBridgeModule协议,你的类需要包含RCT_EXPORT_MODULE()宏。这个宏也可以添加一个参数用来指定在Javascript中访问这个模块的名字。如果你不指定,默认就会使用这个Objective-C类的名字。
// CalendarManager.m @implementation CalendarManager RCT_EXPORT_MODULE(); @end //支付宝支付 RCT_EXPORT_METHOD(onAliPay:(NSString *)orderString resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { //模块代码 }
现在从Javascript里可以这样调用这个方法:
import { NativeModules } from 'react-native'; var pay = NativeModules.ReactNativePay; Pay.onAliPay(payStr) .then((message)=>{ console.log("message" + message); if(message !== "") //支付成功的处理 this.refs.toast.show(message, DURATION.LENGTH_SHORT); }) .catch(e=>{ console.log("e.message" + e.message); if(e.message !== "") this.refs.toast.show(e.message, DURATION.LENGTH_SHORT); if(e.code === '-1' || e.message === '支付失败') { //支付失败 } })
注意: 导出到Javascript的方法名是Objective-C的方法名的第一个部分。React Native还定义了一个RCT_REMAP_METHOD()宏,它可以指定Javascript方法名。当许多方法的第一部分相同的时候用它来避免在Javascript端的名字冲突。
二、参数类型
  RCT_EXPORT_METHOD 支持所有标准JSON类型,包括:
- string (NSString)
- number (NSInteger,float,double,CGFloat,NSNumber)
- boolean (BOOL,NSNumber)
- array (NSArray) 包含本列表中任意类型
- object (NSDictionary) 包含string类型的键和本列表中任意类型的值
- function (RCTResponseSenderBlock)
  除此以外,任何RCTConvert类支持的的类型也都可以使用(参见RCTConvert了解更多信息)。RCTConvert还提供了一系列辅助函数,用来接收一个JSON值并转换到原生Objective-C类型或类。如下:
RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location date:(nonnull NSNumber *)secondsSinceUnixEpoch) { NSDate *date = [RCTConvert NSDate:secondsSinceUnixEpoch]; } 或 RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location date:(NSString *)ISO8601DateString) { NSDate *date = [RCTConvert NSDate:ISO8601DateString]; }
三、回调函数
原生模块还支持一种特殊的参数——回调函数。它提供了一个函数来把返回值传回给JavaScript。如下:
typedef void (^RCTResponseSenderBlock)(NSArray *response); typedef void (^RCTResponseErrorBlock)(NSError *error); typedef void (^RCTPromiseResolveBlock)(id result); typedef void (^RCTPromiseRejectBlock)(NSString *code, NSString *message, NSError *error);
四、实例代码(一)
(1)原生代码
//.h文件 #import <React/RCTBridgeModule.h> #import <React/RCTLog.h> @interface RNMethodTool : NSObject <RCTBridgeModule> @end //.m文件 #import "RNMethodTool.h" #import "AppDelegate.h" @implementation RNMethodTool //这个宏必须要写的,否则RN找不到该类 RCT_EXPORT_MODULE() RCT_EXPORT_METHOD(doSomething:(NSString *)string){ //这也是暴露给RN的方法,弹出系统框,stirng是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]; }); } @end
(2)在JS端的应用
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View,NativeModules,TouchableHighlight} from 'react-native';
const methodTool = NativeModules.RNMethodTool;
type Props = {};
export default class App extends Component<Props> {
  render() {
    return (
      <View style={styles.container}>
        <TouchableHighlight onPress={()=>methodTool.doSomething("我是rn传过来的数据")}>
          <Text style={styles.welcome}>Welcome to React Native!</Text>
        </TouchableHighlight>
      </View>
    );
  }
  
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});  五、实例代码(二)
原生端
//.h文件 #import <Foundation/Foundation.h> #import <React/RCTBridgeModule.h> @interface NativeInteraction : NSObject <RCTBridgeModule> @end //.m实现文件 #import "NativeInteraction.h" #define TestNativeJsonData @"{\"callback1\":\"123\",\"callback2\":\"asd\"}" @implementation NativeInteraction { RCTPromiseResolveBlock _resolveBlock; RCTPromiseRejectBlock _rejectBlock; } RCT_EXPORT_MODULE(); RCT_EXPORT_METHOD(RNTransferIOS) { NSLog(@"RN调用iOS"); } RCT_EXPORT_METHOD(RNTransferIOSWithParameter:(NSString *)logString) { NSLog(@"来自RN的数据:%@",logString); } RCT_EXPORT_METHOD(RNTransferIOSWithCallBack:(RCTResponseSenderBlock)callback) { callback(@[[NSString stringWithFormat:@"来自iOS Native的数据:%@",TestNativeJsonData]]); } RCT_REMAP_METHOD(RNTransferIOSWithParameterAndCallBack, para1:(NSString *)para1 para2:(NSString *)para2 resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)reject) { NSLog(@"来自RN的数据:para1——%@, para2——%@",para1, para2); _resolveBlock=resolver; _rejectBlock=reject; NSString *jsonString = TestNativeJsonData; _resolveBlock(@[jsonString]); } @end
在JS端的应用
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, DeviceEventEmitter, Alert, Button, NativeModules} from 'react-native';
const NativeInteraction = NativeModules.NativeInteraction;
type Props = {};
export default class App extends Component<Props> {
  constructor(props) {
    super(props);
    this.state = {
        notice: '默认值',
    };
  }
  componentWillMount() {
      DeviceEventEmitter.addListener('EventInit', (msg) => {
          let receive = "EventInit: " + msg;
          console.log(receive);
          this.setState({notice: receive});
      });
      DeviceEventEmitter.addListener('EventLogin', (msg) => {
          let receive = "EventLogin: " + msg;
          console.log(receive);
          this.setState({notice: receive});
      });
  }
  transferIOS = () => {
    NativeInteraction.RNTransferIOS();
  }
  transferIOS1 = () => {
    NativeInteraction.RNTransferIOSWithParameter('{\'para1\':\'rndata1\',\'para2\':\'rndata2\'}');
  }
  transferIOS2 = () => {
    NativeInteraction.RNTransferIOSWithCallBack((data) => {
      this.setState({notice: data});
    });
  }
  transferIOS3 = () => {
    NativeInteraction.RNTransferIOSWithParameterAndCallBack('rndata1','rndata2').then(result =>{
      let jsonString = JSON.stringify(result);
      this.setState({notice: jsonString});
    }).catch(error=>{
    });
  }
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>第一个React Native页面</Text>
        <Text style={styles.instructions}>{this.state.notice}</Text>
        <Button
          onPress={this.transferIOS}
          title="RN调用iOS(无回调无参数)"
          color="#841584"
          />
        <Button
          onPress={this.transferIOS1}
          title="RN调用iOS(有参数)"
          color="#841584"
          />
        <Button
          onPress={this.transferIOS2}
          title="RN调用iOS(有回调)"
          color="#841584"
          />
        <Button
          onPress={this.transferIOS3}
          title="RN调用iOS(有参数有回调)"
          color="#841584"
          />
      </View>
    );
  }
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});  
参考资料:https://www.jianshu.com/p/5f5c50638b2e 感谢这位大佬。



 京公网安备 11010502036488号
京公网安备 11010502036488号