开发react-native与iOS时回用到两端通信的情况,今天说下iOS调用RN的两种写法
一:自己不实例化RCTEventEmitter子类,在iOS中用发送通知方法进行调用
二:自己实例化RCTEventEmitter子类,进行添加JS回调
一:自己不实例化RCTEventEmitter子类,在iOS中用发送通知方法进行调用
1、建立RNBridgeModule类继承与RCTEventEmitter,遵守RCTBridgeModule协议
RNBridgeModule.h文件如下
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import <UIKit/UIKit.h>
#import <React/RCTEventEmitter.h>
NS_ASSUME_NONNULL_BEGIN
@interface RNBridgeModule : RCTEventEmitter <RCTBridgeModule>
@end
NS_ASSUME_NONNULL_END
2、RNBridgeModule.m文件先实现父类的supportedEvents方法
-(NSArray*)supportedEvents {
return@[eventName1,eventName2];
}
3、实现父类的startObserving方法,里面通知的添加
- (void)startObserving {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(CollectionProductSuccessForRNAction:)
name:@"notificationName1"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(CollectionProductSuccessForRNAction:)
name:@"notificationName2"
object:nil];
}
4、实现通知的回调方法CollectionProductSuccessForRNAction
- (void)CollectionProductSuccessForRNAction:(NSNotification*)notification {
dispatch_async(dispatch_get_main_queue(), ^{
if ([notification.name isEqualToString:@"notificationName1"]) {
[self sendEventWithName:@"eventName1" body:nil];
}else if ([notification.name isEqualToString:@"notificationName2"]) {
[self sendEventWithName:@"eventName2" body:nil];
}
});
}
5、实现父类的stopObserving移除通知
- (void)stopObserving {
[[NSNotificationCenter defaultCenter]removeObserver:self name:@"notificationName1"object:nil];
[[NSNotificationCenter defaultCenter]removeObserver:self name:@"notificationName2"object:nil];
}
6、在需要执行RN代码的地方发送通知就可以了
[[NSNotificationCenter defaultCenter]postNotificationName:@"notificationName1" object:nil];
7、用通知发送不用自己实例化RNBridgeModule类了,在加载RN时回自动实例化,并且RNBridgeModule的父类RCTEventEmitter并没有把实例化方法放出来
+ (void)initialize
{
if (self != [RCTEventEmitter class]) {
RCTAssert(RCTClassOverridesInstanceMethod(self,@selector(supportedEvents)),
@"You must override the `supportedEvents` method of %@", self);
}
}
initiali方法回加载支持的方法evenName,如果自己实例化RNBridgeModule类,需要把rootView的bridge传过来才可以获取到支持的eventName,这里就设涉及到第二种方法了
8、相对应的RN中的JS代码
创建EventManager.js
import React, {
NativeModules,
Platform,
NativeEventEmitter,
DeviceEventEmitter
}from 'react-native';
var NativeModulesByIOS = NativeModules.MJRNBridgeModule;
const NativeNotificationMoudule = new NativeEventEmitter(NativeModulesByIOS)
export default class EventManager{
subscription = null; //监听者
/**
* @param eventType 监听的名称,用来区分监听,String类型
* @param callback 监听的回调,需要监听的方法
*/
init = (eventType,callback) =>{
if (Platform.OS === 'ios') {
subscription = NativeNotificationMoudule.addListener(
eventType,
(reminder) => {
callback();
}
);
} else {
subscription = DeviceEventEmitter.addListener(eventType,() => {
callback();
});
}
}
/**
* 销毁监听
*/
destroy=()=>{
if (this.subscription != null) {
subscription.remove();
}
}
}
在相应的组件内实例化EventManager,并添加监听
componentDidMount() {
this.eventManager = new EventManager();//创建
this.eventManager.init('RefreshCreditCardPage', this._onHeaderRefresh);//注册事件
}
二、自己实例化RCTEventEmitter子类,进行添加JS回调
1、建立RNBridgeModule类继承与RCTEventEmitter,遵守RCTBridgeModule协议
RNBridgeModule.h如下
#import
#import
#import
#import
NS_ASSUME_NONNULL_BEGIN
externNSString*constrefreshLoanMarkPage;
externNSString*constrefreshCreditCardPage;
@interface RNBridgeModule : RCTEventEmitter <RCTBridgeModule>
//设置单利
+ (instancetype)shareInstance;
//调用RN的方法API
- (void)sendEventWithName:(NSString*)eventName;
@end
NS_ASSUME_NONNULL_END
2、在RNBridgeModule.m实现单例方法和其父类的supportedEvents方法
+ (instancetype)shareInstance {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
-(NSArray*)supportedEvents {
return@[eventName1,eventName2];
}
3、实现调用RN的方法sendEventWithName
- (void)sendEventWithName:(NSString*)eventName {
[self.bridge enqueueJSCall:@"RCTDeviceEventEmitter" method:@"emit" args:@[eventName] completion:NULL];
}
4、在需要调用RN方法的地方获取RNBridgeModule单例,并把RNBridgeModule的bridge设置成RCTRootView的bridge,bridge在父类RCTEventEmitter里定义的
#import "RNBridgeModule.h"
#import <React/RCTRootView.h>
@property (nonatomic, strong) RCTRootView *rnView;
@property (nonatomic, strong) RNBridgeModule *bridgeToRNModule;
self.bridgeToRNModule = [RNBridgeModule shareInstance];
[self.bridgeToRNModule setValue:self.rnView.bridge forKey:@"bridge"];
5、调用RN接口
[self.bridgeToRNModule refreshPageWithEventName:@"eventName1"];
6、添加RN中的js代码
创建EventManager.js,这种方法添加监听只需要和Android一种即可,不用判断平台了。
import React, {
NativeModules,
Platform,
NativeEventEmitter,
DeviceEventEmitter
}from 'react-native';
var NativeModulesByIOS = NativeModules.MJRNBridgeModule;
const NativeNotificationMoudule = new NativeEventEmitter(NativeModulesByIOS)
export default class EventManager{
subscription = null; //监听者
/**
* @param eventType 监听的名称,用来区分监听,String类型
* @param callback 监听的回调,需要监听的方法
*/
init = (eventType,callback) =>{
subscription = DeviceEventEmitter.addListener(eventType,() => {
callback();
});
}
/**
* 销毁监听
*/
destroy=()=>{
if (this.subscription != null) {
subscription.remove();
}
}
}
componentDidMount() {
this.eventManager = new EventManager();//创建
this.eventManager.init('RefreshCreditCardPage', this._onHeaderRefresh);//注册事件
}
这样两种实现就实现了,第二种方法就是把RCTEventEmitter扒了一层皮,直接重新实现RCTEventEmitter类。
在此谢谢大家的喜欢,谢谢支持。
网友评论