【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 ...
随机推荐
- 手摸手教你编写你人生中第一个HTML页面
本文是<HTML5与CSS3基础语法自学教程>的第二篇,首发于[前端课湛]微信公众号. 导读:本小节主要讲解 HTML 的基础语法内容,将通过编写第一个 HTML 页面来学习 HTML 的 ...
- 后台管理tab栏滑动解决方案
后台管理系统中比较常见的布局是左边菜单栏,右边tab切换栏,但是一般的tab组件不包含tab页过多的切换问题的,所以需要个性化实现,本文的实现方案是滑动鼠标滚轮绑定tab达到切换的效果,先上一个动态图 ...
- GeoServer 2.15.0版本跨域问题解决方法
geoserver默认不开启跨域设置,开启步骤如下: 1.修改配置文件web.xml,该配置文件的路径如下 \webapps\geoserver\WEB-INF\web.xml 2.搜索:cross- ...
- 使用VS2005编译安装openssl1.1.1c
1.首先获取openssl源码包 openssl-1.1.1c.tar.gz: 2.安装 ActivePerl: 2.解压源码包,打开vs2005命令行工具,通过命令行进入openssl源码包根目录: ...
- flutter_boot android和flutter源码阅读记录
版本号0.1.54 看源码之前,我先去看下官方文档,对于其源码的设计说明,文中所说的原生都是指android 看完官方文档的说明,我有以下几个疑问 第一个:容器是怎么设计的? 第二个:native和f ...
- vue组件常用声明方式
一.前言 这是自己重新写的一个,感觉以前的太写了很多不必要的方式 实际当中基本不会用的 所以自己写了一个常用的组件什么方式 更加的通俗易懂 二.代码如下 <!DOCTYPE html> & ...
- Spring Boot 静态资源能加载css 不能加载js
Spring Boot 配置拦截器的时候默认 是放行 静态资源 , 也就是说不需要进行配置 registry.addResourceHandler("/**") .addResou ...
- EntityFramework中实体类到表名的批量映射
在使用EntityFramework做CodeFirst开发时,经常需要将实体类映射到数据库表,但是C#实体类和数据库表中的命名遵循的是不同的规范,这就需要为每个实体类做一个到数据库表名的映射.大多情 ...
- Java生鲜电商平台-深入理解微服务SpringCloud各个组件的关联与架构
Java生鲜电商平台-深入理解微服务SpringCloud各个组件的关联与架构 概述 毫无疑问,Spring Cloud是目前微服务架构领域的翘楚,无数的书籍博客都在讲解这个技术.不过大多数讲解还停留 ...
- C# net core程序调试错误集(持续更新)
目录 C#程序调试错误集 1.依赖注入错误System.InvalidOperationException: Unable to resolve service for type 'xxx' whil ...