【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 ...
随机推荐
- 精通awk系列(13):print、printf、sprintf和重定向
回到: Linux系列文章 Shell系列文章 Awk系列文章 输出操作 awk可以通过print.printf将数据输出到标准输出或重定向到文件. print print elem1,elem2,e ...
- Angular 彻底解决 Dropdown 在 Safari 上无法自动关闭的问题
之前在 Safari 上用 focus 事件来实现 Dropdown 下拉菜单,结果在 iOS 上不兼容. 尝试了 MDN 和 stack over flow 上各种奇技淫巧,然而在 iOS 上全都败 ...
- C#开发微信小程序(五)
导航:C#开发微信小程序系列 关于小程序项目结构,框架介绍,组件说明等,请查看微信小程序官方文档,关于以下贴出来的代码部分我只是截取了一些片段,方便说明问题,如果需要查看完整源代码,可以在我的项目库中 ...
- 致初学者:零基础如何学好,Python这门编程语言?
前言对于很多Python这门编程语言的初学者,往往会面临以下问题: Python2和Python3我该学习哪一个?是否要安装Linux系统学习Python?Python3有各种版本我该安装哪一个?那么 ...
- Spring Cloud @RefreshScope刷新问题
问题 使用@RefreshScope会刷新在sprign ioc中所有bean中使用@Value的值,但是在配置类中使用方法去配置的其他类参数并不会改变例如 解决方案 //使用此方法监听事件 @Eve ...
- JavaWeb中的MVC
不使用什么MVC的案例分析: 利用Servlet与jsp实现登陆请求,数据库查询,以及页面的跳转逻辑 具体流程如下: 不做任何结构上的考虑,可以简单的做如下实现: 目录结构 LoginServlet ...
- Localize UI Elements 汉化界面(本地化)
In this lesson, you will learn the basics of localizing visible UI elements. By default, the applica ...
- iOS正则表达式解决实际问题
问题:上海市徐汇区桂林路158号1202室 字符串长度不固定,数字长度也不固定.截取第二组数字. 方法一:[正则表达式] NSString * str = @"上海市徐汇区桂林路158号12 ...
- 增加sudo用户访问oracle
增加zgy用户可以访问数据库[root@DBDATA ~]# useradd zgy--设置密码[root@DBDATA ~]# passwd zgy--设置组[root@DBDATA ~]# use ...
- 使用Apollo动态修改线上数据源
前言 最近需要实现一个功能,动态刷新线上数据源环境,下面来使用Apollo配置中心和Spring提供的AbstractRoutingDataSource来实现. 具体实现 Apollo是携程开源的统一 ...