我爱编程

RN与JS交互之-封装iOS原生模块

2017-11-11  本文已影响275人  lzh_coder

本文要讲的交互场景是JS调用原生方法,最后由原生方法将结果回调到JS里面。

react-native是在原生的基础上,将接口调用统一为js。也就是说,react-native调起原生的能力非常重要。

本文基于react-native 0.44.3

1,引入头文件

#import <React/RCTBridgeModule.h>

2,遵守协议

@interface BaseNativeModule :  NSObject  <RCTBridgeModule>

3,导出模块

@implementation  BaseNativeModule

RCT_EXPORT_MODULE( moduleName ); //用于导出模块,可以设置导出的模块名,默认就是类名。

@end

4,导出方法:

RCT_EXPORT_METHOD(addEvent:(NSString*)name location:(NSString*)location)

{

//在js控制台上打印log信息。

RCTLogInfo(@"Pretending to create an event %@ at %@", name, location);

}

这个方法是一个实例方法。

5,js端调用。

import  { NativeModules } from 'react-native

NativeModules.XXX.addEvent( param1, param2 );

需要注意,jsbundle加载需要一个js线程,在jsbundle加载的时候,react-native会去配置NativeModules,它是一个对象,或者看成是一个map,key就是模块名,value就是原生的对象。一个key对应的原生对象只有一个,也就是说无论在RN页面的哪个地方调用这个原生模块,实际调用的是同一个对象,需要考虑对象状态的问题。

6,js回调

桥接到Javascript的方法返回值类型必须是void。React Native的桥接操作是异步的,在queue里面异步执行,所以如果要返回结果给Javascript,就必须通过回调或者触发事件来进行。这里讲的是回调。回调对应于iOS端就是通过block来回调的。

js回调的特点,发起方是js,必须是js端先发起,然后由native方回调结果到js端处理。

6.1 RCTResponseSenderBlock

这个block接受一个数组参数,数组里面有两个元素,第一个参数用于表示错误信息,第二个参数可以是一个数组,也可以是一个对象,总之第二个代表原生方法的返回结果,第一个代表获取成功还是失败。

6.2 Promise样式的回调。一般用于js端try-catch结构,和Promise调用。

RCTPromiseResolveBlock,对应js里面的resolve。

RCTPromiseRejectBlock,对应js里面的reject。

7,多线程

js代码的执行是在js线程里面,原生模块的执行默认是在一个串行的GCD queue里面异步执行的。对于原生模块的执行来说,默认一个串行的GCD queue是不够的,我们有时候需要指定模块所有任务执行所在的queue。

这个可以通过重写methodQueue的getter方法

 - (dispatch_queue_t)methodQueue

{

return dispatch_get_main_queue();

}

此外,如果一个模块里面的几个任务,个别任务需要在一个特殊的线程里面执行,那么只去在任务执行的逻辑里面,指定该任务执行所在的线程。

RCT_EXPORT_METHOD(doSomethingExpensive:(NSString *)param callback:(RCTResponseSenderBlock) callback)

{

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{

        // 在这里执行长时间的操作...

        // 你可以在任何线程/队列中执行回调函数callback(@[...]); });

}

在模块之间共享分发队列:

 methodQueue方法会在模块被初始化的时候被执行一次,然后会被React Native的桥接机制保存下来,所以你不需要自己保存队列的引用,除非你希望在模块的其它地方使用它。但是,如果你希望在若干个模块中共享同一个队列,则需要自己保存并返回相同的队列实例;仅仅是返回相同名字的队列是不行的。

8,参数类型转换。

js与原生互相调用,除了方法签名的不同,参数类型也是不同的,要把参数类型对应起来。react-native框架本身做了一些转换。包括下面这些:

string (NSString)

number ( NSInteger, float, double, CGFloat, NSNumber)

boolean (BOOL,NSNumber)

array (NSArray) 包含本列表中任意类型

object (NSDictionary) 包含string类型的键和本列表中任意类型的值

function (RCTResponseSenderBlock)

除此以外,任何RCTConvert类支持的的类型也都可以使用(参见RCTConvert了解更多信息)。RCTConvert还提供了一系列辅助函数,用来接收一个JSON值并转换到原生Objective-C类型或类。


上一篇下一篇

猜你喜欢

热点阅读