本篇针对 iOS
参考链接
官方文档,查看 Sending Events to JavaScript
简书的参考文章
stack overflow 原理介绍
概述
本篇主要是一个踩坑的笔记。
实际开发中,经常会需要ios
和rn
,或者说OC/Swift
与JS
之间的通信。
一个实际的应用场景描述:
我有 A,B 两个页面,A 页面是 Native, B 页面是 RN, 现在在 A 页面做了一个提交操作,提交成功后,需要跳转到 B 页面,并通知 B 页面刷新。
官方的文档描述Sending Events to JavaScript
有几个坑。如果只是简单的继承RCTEventEmitter
然后写一个发送消息,通常情况下原生这边是会闪退,报:
bridge is not set. This is probably because you've " "explicitly synthesized the bridge in %@, even though it's inherited " "from RCTEventEmitter.
这里要做以下的几个说明。
说明
一个重要的原则就是:
桥接必须要把 Native
和 React Native
两边都写好才可以。好比一座桥的两端,如果你只是写好一端的话,另一端路走不通,还是会报错的。
下面是参考代码
OC
.h
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
#import "React/RCTBridge.h"
@interface SendMessageToRN: RCTEventEmitter<RCTBridgeModule>
- (void)needRefreshMyFeedbackList:(NSNotification *)notification;
@end
.m
#define RefreshListMsg @"RefreshListMsg" // 记住这这个,相当于广播名
@implementation SendMessageToRN
RCT_EXPORT_MODULE(RefreshMyFeedback); //这行一定要写,并且记住括号内的名称,且和 RN 中的代码保持一致
- (NSArray<NSString *> *)supportedEvents {
return @[RefreshListMsg,];
}
// 可以使用这个单例来做
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static SendMessageToRN *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [super allocWithZone:zone];
});
return sharedInstance;
}
- (void)needRefreshMyFeedbackList:(NSNotification *)notification {
if (self.bridge) {// 务必加一个判断,万一 RN 那端桥接没有做好,不至于崩溃
[self sendEventWithName:RefreshListMsg body:@{}];
}
}
调用的时候,使用单例,然后调用代码
SendMessageToRN *sendMsg = [SendMessageToRN allocWithZone:nil];
[sendMsg needRefreshMyFeedbackList:nil];
JS 这端的代码
import {
StyleSheet, View, Dimensions, Text, NativeEventEmitter, NativeModules
} from 'react-native';
//...省略部分代码
componentWillMount() {
//RefreshMyFeedback就是上面定义的 RCT_EXPORT_MODULE(RefreshMyFeedback);
let nativeBridge = NativeModules.RefreshMyFeedback;
let refreshEmitter = new NativeEventEmitter(nativeBridge);
this.listener = refreshEmitter.addListener(
'RefreshListMsg',// RefreshListMsg就是 OC 那边定义的广播名
(reminder) => {
console.log(reminder.name);
this._onRefresh();
}
);
}
componentDidMount() {
this._onRefresh();
}
componentWillUnmount() {
this.listener.remove();// 用完记得销毁掉
}