1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 【React Native】在原生和React Native间通信(RN调用原生)

【React Native】在原生和React Native间通信(RN调用原生)

时间:2023-04-11 16:01:57

相关推荐

【React Native】在原生和React Native间通信(RN调用原生)

一、从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 CalendarManagerRCT_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><ButtononPress={this.transferIOS}title="RN调用iOS(无回调无参数)"color="#841584"/><ButtononPress={this.transferIOS1}title="RN调用iOS(有参数)"color="#841584"/><ButtononPress={this.transferIOS2}title="RN调用iOS(有回调)"color="#841584"/><ButtononPress={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,},});

参考资料:/p/5f5c50638b2e感谢这位大佬。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。