序言: React Native无论是在社区和应用程度上,在国内外是十分广泛和普及的。最近总结了下RN关于IOS和Android的通信,希望大家喜欢,文章末尾有github的Demo地址。本文参照官网来写:地址跳转
-
一、IOS通信——直接调用,Callback,Promise
你可以在JavaScript通过NativeModules调用原生组件,原生方法,通过NativeEventEmitter进行添加事件。
在ReactNative中,一个原生模块就是通过“RCTBridgeModule”协议的 Objective-C 类,为了实现RCTBridgeModule协议,你的类需要包含RCT_EXPORT_MODULE()宏,这个宏也可以添加一个参数用来指定在 JavaScript 中访问这个模块的名字。如果你不指定,默认就会使用这个 Objective-C 类的名字。
声明通过RCT_EXPORT_METHOD()宏来实现要给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 类型或类。
下面看代码:
原生实现:
xxx.h
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
///添加RCTBridgeModule协议
@interface LiveModule : NSObject<RCTBridgeModule>
@end
xxx.m ——实现导出给JavaScript的方法。包含Callback和Promise回调
@implementation LiveModule
RCT_EXPORT_MODULE();
///直接调用原生方法
RCT_EXPORT_METHOD(pushLiveViewController: (NSString *)str) {
///rn和原生桥接是异步的,所以需要对UI操作必须在主线程。
dispatch_async(dispatch_get_main_queue(), ^{
UINavigationController *nav = (UINavigationController *)AppDelegate.shareAppDelegate.window.rootViewController;
ViewController *vc = [[ViewController alloc] init];
[nav presentViewController:vc animated:false completion:nil];
});
}
///callback回调
RCT_EXPORT_METHOD(findEvents: (RCTResponseSenderBlock)callback) {
callback(@[[NSNull null], CALL_VALUE]);
}
///promise回调
RCT_EXPORT_METHOD(liveValue: (BOOL)valueI
findEventsWithResolver: (RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
if (valueI == YES) {
resolve(PROMISE_VALUE);
}else {
NSError *error = nil;
reject(@"error", @"This is error!", error);
}
}
JavaScript通过NativeModules调用原生方法
const liveModule = NativeModules.LiveModule;
///直接调用
liveModule.pushLiveViewController('xxx');
//callback方式
liveModule.findEvents((error, value) => {
this.setState({
callText: value,
});
});
//promise方式
liveModule
.liveValue(true)
.then(value => {
this.setState({
promiseText: value,
});
})
.catch(error => {
console.log(error);
});
原生给JavaScript发送事件
最好的方法是继承RCTEventEmitter,实现suppportEvents方法并调用self sendEventWithName:。
@interface LiveEventEmitter : RCTEventEmitter <RCTBridgeModule>
///给js端发送事件
- (void)sendMessageToRN: (NSDictionary *)dict eventName:(NSString *)name;
@end
@interface LiveEventEmitter()
@property(nonatomic, strong)NSArray * nameArrays;
@end
@implementation LiveEventEmitter
RCT_EXPORT_MODULE();
/// 重写方法,添加事件名
-(NSArray<NSString *> *)supportedEvents {
return self.nameArrays;
}
//重写方法,单例获取bridge。如果不重写bridge为nil
+ (id)allocWithZone:(struct _NSZone *)zone {
static LiveEventEmitter *live = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
live = [super allocWithZone:zone];
});
return live;
}
///发送事件给js
- (void)sendMessageToRN: (NSDictionary *)dict eventName:(NSString *)name {
[self sendEventWithName:name body:dict];
}
- (NSArray *)nameArrays {
if (_nameArrays == nil) {
_nameArrays = @[@"EventName"];
}
return _nameArrays;
}
@end
JavaScript订阅事件
//在componentDidMount()中订阅事件
const eventEmitter = new NativeEventEmitter(NativeModules.LiveEventEmitter);
this.listener = eventEmitter.addListener('EventName', value => {
this.setState({
touchText: value.message,
});
});
Demo地址:https://github.com/JoyceRao/React-Native-RNNativeCommunication
网友评论