一、从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 CalendarManagerRCT_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><ButtononPress={this.transferIOS}title="RN调用iOS(无回调无参数)"color="#841584"/><ButtononPress={this.transferIOS1}title="RN调用iOS(有参数)"color="#841584"/><ButtononPress={this.transferIOS2}title="RN调用iOS(有回调)"color="#841584"/><ButtononPress={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 调用原生WebPage 解决微信支付Referer问题

    补充一下: referer送什么值? 一般来说就是商户产品的域名就行 遇到一个问题, 测试环境提供的商户产品与生产环境的域名如果不一致, 也会出现一样的报错 说商户号问题,如果都改造好了, 不妨再招业 ...

  2. React Native手动实现调用原生相机相册(Android端)

    前言 最近一直在学习RN的相关开发,想做一部分调用原生的实现,来练练手,于是就有了下面这个demo,由于本人是Android开发,所以只实现了Android端的效果. Demo 主要实现 这种调用原生 ...

  3. android native 相册,React Native手动实现调用原生相机相册(Android端)

    前言 最近一直在学习RN的相关开发,想做一部分调用原生的实现,来练练手,于是就有了下面这个demo,由于本人是Android开发,所以只实现了Android端的效果. Demo 主要实现 这种调用原生 ...

  4. RN与原生交互(一)——基本页面跳转

    React Native(以下简称RN)开发app过程中大部分都可以在JS端完成,但是也有一些功能是需要原生端来完成的.这时RN与原生端就不可避免的需要进行交互,比如页面跳转和数据传递.本篇文章主要以 ...

  5. JavaScript调用原生API获取手机型号

    跨平台技术简介 针对原生开发面临问题,人们一直都在努力寻找好的解决方案,而时至今日,已经有很多跨平台框架,根据其原理,主要分为三类: H5+原生(Cordova.Ionic.微信小程序) JavaSc ...

  6. JNA调用原生函数 基础入门

     JNA调用原生函数 本文原名<使用JNA方便地调用原生函数>发表于2009年3月的"程序员"杂志上.感谢程序员杂志的许可,使这篇文章能够成为免费的电子版,发布于网络上 ...

  7. flutter 调用原生安卓插件_Flutter 如何调用Android和iOS原生代码

    分3个大步骤: 1.在flutter中调用原生方法 2.在Android中实现被调用的方法 3.在iOS中实现被调用的方法 在flutter中调用原生方法 场景,这里你希望调用原生方法告诉你一个boo ...

  8. flutter 调用原生安卓插件_Flutter 如何调用Android和iOS原生代码-阿里云开发者社区...

    分3个大步骤: 1.在flutter中调用原生方法 2.在Android中实现被调用的方法 3.在iOS中实现被调用的方法 在flutter中调用原生方法 场景,这里你希望调用原生方法告诉你一个boo ...

  9. rn代码与android,RN与原生通讯(安卓篇)

    明天和意外你永远都不知道哪一个先来,编程界亦是如此.例如某个已经有原生代码开发模块的项目要求用RN扩张某些功能:又例如,RN中未封装到的组件非得求助于原生代码.所以RN与原生代码通讯对于混合编程是至关 ...

最新文章

  1. C++ STL: 基本六大部件概览 及 各个容器使用方式和底层实现概览
  2. 数学之美系列14(转帖)
  3. group by的查询
  4. python用电度数设计_在Python中动态模拟时绘制电压大小
  5. 2019.9.18最小生成树知识点总结
  6. python爬取百度百科搜索结果_用Python抓取百度搜索结果,python,爬取,的
  7. 2022经营新增长第一课
  8. 作者:​张群(1988-),女,博士,中国电子技术标准化研究院设备与数据研究室副主任。...
  9. 中英文对照 —— 软件与病毒、电子与硬件
  10. java对象地址连续_Java面向对象中地址的理解(长期修改)
  11. spring boot 教程(四) 统一异常处理
  12. 设置Webdriver启动chrome为默认用户的配置信息
  13. idea中有些类明明在jar包里有,但是却搜不到
  14. mysql服务启动失败原因
  15. 关于数据库查询中的几种连接
  16. 易语言计算机设备获取,易语言获取混音设备名称
  17. android端使用mockServer
  18. Pytorch GAN实战 MINIST手写数字识别分布解析
  19. fleck 客户端_C# Fleck的WebSocket使用
  20. 不同tab页sessionStorage共享情况

热门文章

  1. 《WAP团队项目需求分析改进》
  2. SQL Server 2012 安装过程中出现:试图执行未经授权的操作..
  3. 新唐芯片学习笔记——ADC
  4. 计算机一级考试ms office试题,2017年9月计算机一级MSoffice考试试题.doc
  5. excel表格下载,并设置填充色
  6. python题库大一_大一python选择题题库_python选择题题库 - CSDN
  7. Error: error:0308010C:digital envelope routines::unsupported问题的解决方案包括webstorm运行vue项目的解决方案
  8. C语言数组指针(指向数组的指针)
  9. Transact-SQL语句创建和删除数据库YGKQ(配有详细注释)
  10. ImportError: pycurl: libcurl link-time ssl backend (openssl) is different from compile-time ssl back