【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 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 感谢这位大佬。
【React Native】在原生和React Native间通信(RN调用原生)的更多相关文章
- 简单实现RN调用原生方法(IOS)
在React Native中,一个“原生模块”就是一个实现了“RCTBridgeModule”协议的Objective-C类(个人理解RCTBridgeModule就是react与native之间的桥 ...
- React独立组件间通信联动
React是现在主流的高效的前端框架,其官方文档 http://reactjs.cn/react/docs/getting-started.html 在介绍组件间通信时只给出了父子组件间通信的方法,而 ...
- ReactNative-JS 调用原生方法实例代码(转载)
第一步首先创建ReactNative 模块类继承ReactContextBaseJavaModule package com.mixture; import android.content.Con ...
- 10-IOSCore - 应用间通信、本地通知
一.应用间通信 URL 调用系统服务: tel:11111 sms:xxx@163.com http:// URL深入 类型://主机:端口/地址?参数 label框等于文字大小快捷键:command ...
- Android原生嵌入React Native
1.首先集成的项目目录 我使用的是直接按照react-native init Project 的格式来导入的,也就是说,我的Android项目目录是跟node_modules是在一个目录下的. 我们i ...
- React Native组件间通信
React Native组件间通信 React Native组件的关系有:父子关系.无直接关系.组件间通信主要针对这两类来讨论. 一.父组件和子组件之间通信 父组件向子组件传递消息.数据通过对子组件的 ...
- Native VS H5 VS React Native
现在软件行业已经跨入大前端时代,所以势必学一点前端的知识.本来移动端开发都是使用各自平台的语言,如iOS端使用OC,swift:Android使用java,但是随着H5的出现,导致移动端Native出 ...
- react native 0.50与OC交互 && Swift与RN交互
新公司也打算做rn,还是得捡起来再度学习.开撸! react native一个版本一个样子,之前写的rn与iOS交互系列在最新版本中有点出入(0.50.4版本).今天填一下坑. 首先上npm版本,re ...
- Hybrid APP基础篇(二)->Native、Hybrid、React Native、Web App方案的分析比较
说明 Native.Hybrid.React.Web App方案的分析比较 目录 前言 参考来源 前置技术要求 楔子 几种APP开发模式 概述 Native App Web App Hybrid Ap ...
随机推荐
- iOS----------证书的制作
https://developer.umeng.com/docs/66632/detail/66748#createappid Certificates-> 卫生许可证 identifiers ...
- Linux 命令行初始化MySQL数据库
作为一个技术纯小白,在Linux服务器初始化MySQL数据库的时候遇到了一点小问题: 1.不会使用MySQL图形工具,几乎没玩过 2.客户的VPN没有开放3306端口,没法用navicat等工 ...
- 安装最新版 windows正版软件地址(visio,office)
链接地址为 https://msdn.itellyou.cn/ 进入后直接搜 然后复制链接使用迅雷下载 很快完成 但是都是原生的 需要破解 提供一个visio的破解软件 亲测有效 链接:https:/ ...
- .NET Core 3.0正式版发布
是的,.NET Core 3.0正式版发布了,令人兴奋. WPF 其实,.NET Core 2.1开始已经是个很完善的版本,3.0又带来了什么呢?我站在我的使用角度来看,最最令人振奋的就是:能用WPF ...
- ReactNative: 使用对话框组件AlertIOS组件
一.简介 在使用一款App的时候,经常会用到对话框进行信息的友好提示,一般简单要求性不高的时候我们可以使用web提供的alert实现即可.但是,对于需要交互性和美观性的对话框,alert就明显无法满足 ...
- SpringCloud断路器(Hystrix)
一.为什么需要 Hystrix? 在微服务架构中,我们将业务拆分成一个个的服务,服务与服务之间可以相互调用(RPC).为了保证其高可用,单个服务又必须集群部署.由于网络原因或者自身的原因,服务并不能保 ...
- NET Framework项目移植到NET Core上踩的坑(1)
本文章向大家介绍NET Framework项目移植到NET Core上遇到的一系列坑,主要包括NET Framework项目移植到NET Core上遇到的一系列坑使用实例.应用技巧.基本知识点总结和需 ...
- Python程序设计 测验易错题总结
1.温度转换 t=input() if t[-1]=="J": t=int(t[:-1]) t1=t/4.186 print("%.3fcal"%t1) els ...
- 基于SpringBoot前后端分离的点餐系统
基于SpringBoot前后端分离的点餐系统 开发环境:主要采用Spring boot框架和小程序开发 项目简介:点餐系统,分成卖家端和买家端.买家端使用微信小程序开发,实现扫码点餐.浏览菜单.下单. ...
- Go Modules使用教程
Go Modules 不完全教程 文章转载自公众号 Golang 成神之路 , 作者 L Go Modules 是 Golang 官方最近几个版本推出的原生的包管理方式,在此之前,社区也不乏多种包管理 ...