一、从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 (NSIntegerfloatdoubleCGFloatNSNumber)
  • boolean (BOOLNSNumber)
  • 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 感谢这位大佬。

【React Native】在原生和React Native间通信(RN调用原生)的更多相关文章

  1. 简单实现RN调用原生方法(IOS)

    在React Native中,一个“原生模块”就是一个实现了“RCTBridgeModule”协议的Objective-C类(个人理解RCTBridgeModule就是react与native之间的桥 ...

  2. React独立组件间通信联动

    React是现在主流的高效的前端框架,其官方文档 http://reactjs.cn/react/docs/getting-started.html 在介绍组件间通信时只给出了父子组件间通信的方法,而 ...

  3. ReactNative-JS 调用原生方法实例代码(转载)

    第一步首先创建ReactNative 模块类继承ReactContextBaseJavaModule package com.mixture;   import android.content.Con ...

  4. 10-IOSCore - 应用间通信、本地通知

    一.应用间通信 URL 调用系统服务: tel:11111 sms:xxx@163.com http:// URL深入 类型://主机:端口/地址?参数 label框等于文字大小快捷键:command ...

  5. Android原生嵌入React Native

    1.首先集成的项目目录 我使用的是直接按照react-native init Project 的格式来导入的,也就是说,我的Android项目目录是跟node_modules是在一个目录下的. 我们i ...

  6. React Native组件间通信

    React Native组件间通信 React Native组件的关系有:父子关系.无直接关系.组件间通信主要针对这两类来讨论. 一.父组件和子组件之间通信 父组件向子组件传递消息.数据通过对子组件的 ...

  7. Native VS H5 VS React Native

    现在软件行业已经跨入大前端时代,所以势必学一点前端的知识.本来移动端开发都是使用各自平台的语言,如iOS端使用OC,swift:Android使用java,但是随着H5的出现,导致移动端Native出 ...

  8. react native 0.50与OC交互 && Swift与RN交互

    新公司也打算做rn,还是得捡起来再度学习.开撸! react native一个版本一个样子,之前写的rn与iOS交互系列在最新版本中有点出入(0.50.4版本).今天填一下坑. 首先上npm版本,re ...

  9. Hybrid APP基础篇(二)->Native、Hybrid、React Native、Web App方案的分析比较

    说明 Native.Hybrid.React.Web App方案的分析比较 目录 前言 参考来源 前置技术要求 楔子 几种APP开发模式 概述 Native App Web App Hybrid Ap ...

随机推荐

  1. C# HttpClient以multipart/form-data形式 提交文件和其它参数

    调用文件接口,需要一个上传文件和一个Region参数,参考调用实例 public async Task<WebApiResult> UploadFile(UploadFileModel i ...

  2. 如何快速将多个excel表格的所有sheet合并到一个sheet中

    1.将需要合并的excel文件放在同一个文件夹下: 2.新建一个excel表格并打开,右键sheet1,查看代码,然后复制下方的代码到代码框里,点击菜单栏中的“运行”–“运行子过程/用户窗体”,等待程 ...

  3. 定制Dynamics 365 Portal 界面

    1.通过Portal Designer直接进行定制 以管理员用户登录Portal后会出现Portal Designer,可以进行对homepage的部分元素及Navigation直接进行定制 2.通过 ...

  4. DataGridView重新加载数据后,选中上次选中的行。

    public int SelecedRow;//记录当前鼠标点中的行索引(用于解决用户获取看板数据,刷新数据后,当前选中行回到默认行) private void dataGridView1_CellC ...

  5. Android Studio中的AndroidManifest.xml文件分析

    一.关于AndroidManifest.xml AndroidManifest.xml清单文件是每个Android程序中必须的文件,它是整个Android程序的全局描述文件,除了能声明程序中的Acti ...

  6. Flask 教程 第十四章:Ajax

    本文翻译自The Flask Mega-Tutorial Part XIV: Ajax 这是Flask Mega-Tutorial系列的第十四部分,我将使用Microsoft翻译服务和少许JavaSc ...

  7. Redis缓存NoSQL

    下面是一些关于Redis比较好的文章,因为篇幅较大,我就将其折叠起来了.不太喜欢分不同的笔记去记载,除非真的很多很多.所以本文不仅要对Redis做简单的介绍,还要分别介绍Redis中的五种结构,并会贴 ...

  8. [转]UiPath Installing the Firefox Extension

    本文转自:https://docs.uipath.com/studio/lang-en/v2019/docs/installing-the-firefox-extension From UiPath ...

  9. Dynamics 365 Customer Enagement中的更改跟踪(change tracking)

    我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...

  10. Xcode真机运行报错iPhone has denied the launch request

    1.打开钥匙串 ->Apple Worldwide Developer Relations Certification Authority ->双击 并点击信任->选择使用系统默认2 ...