一、从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调用原生)的更多相关文章

  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. Cesium案例解析(一)——HelloWorld

    目录 1. 概述 2. 实例 2.1. HelloWorld.html 2.2. HelloWorld.js 3. 结果 1. 概述 感觉网上已经有不少关于cesium的教程了,但是学习一个框架最快的 ...

  2. Android WebView 加载富文本内容

    WebView加载数据的方式有两种: 1. webView.loadUrl(data);//加载url 2. webView.loadDataWithBaseURL(null,data, " ...

  3. ASP.NET Core on K8S深入学习(11)K8S网络知多少

    本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 一.Kubernetes网络模型 我们都知道Kubernetes作为容器编排引 ...

  4. jquery.i18n 网站呈现各国语言

    在做网站的时候可能会遇到不同语言切换的问题,实现的方法有很多种,本篇文章按照 js 加载的方法的来实现. 应用到的 js 文件: jquery.i18n.properties.js jquery.js ...

  5. Flask 教程 第十章:邮件支持

    本文翻译自The Flask Mega-Tutorial Part X: Email Support 这是Flask Mega-Tutorial系列的第十部分,在其中我将告诉你,应用如何向你的用户发送 ...

  6. ES-结构化查询

    参考: https://es.xiaoleilu.com/054_Query_DSL/55_Request_body_search.html 请求体查询 GET /_search {} 分页 GET ...

  7. C#调试程序——断点+几种观察数据的方法

    目录 C#调试程序--断点+观察数据的方法 1.写本文的背景 2.调试与测试 3.断点调试 3.1 F10 3.2 F11 3.3 SHIFT+F11 4.监视 4.1 按照1方法打断点,单步调试. ...

  8. 一文读懂AOE到底是什么!

    一.背景 1.1 AoE是什么 AoE (AI on Edge) 是一个滴滴开源的终端侧AI集成运行时环境(IRE).以 “稳定性.易用性.安全性” 为设计原则,帮助开发者将不同框架的深度学习算法轻松 ...

  9. Java学习笔记-Java文件操作流

     day03 输入输出流:读入写出  节点流:   有明确的来源和去向   往往对字节操作 节点流又叫低级流.字节流   处理流:  没有明确的来源和去向  往往对低级流或其他高级流进行操作,不能独立 ...

  10. nginx配置文件 http 强跳转 https

    路径 /usr/local/nginx/conf/conf.d/test.jackcui.com.conf server { listen 80; server_name test.jackcui.c ...