iOS开发-与ReactNative交互时bridge is not set.

上次说到了与RN交互时,RN引用原生UI组件时出现的坑,如果说上次的坑是因为没有仔细看官方文档导致的,这次的坑应该算是RN自己的问题了吧。

这次的问题是当原生端主动向RN(JS)发送请求的时候,会崩溃,报错显示

1
2
3
bridge is not set. This is probably because you've "
"explicitly synthesized the bridge in %@, even though it's inherited "
"from RCTEventEmitter.

场景

这次的需求是,需要RN方面开启一个NativeEventEmitter,这个东西类似于iOS中的NSNotificationCenter,用于监听通知。当原生部分需要主动跟RN进行通信的时候,就可以发出一个广播,RN方监听到这个广播之后就会做对应的事情。

还是一样,我们从官方文档入手,官方文档中写的内容也不多,一屏就能显示全:

logo

ok,我们也是一样,还是照着官方文档撸代码。

先写一个继承于RCTEventEmitter的类,然后实现RCTBridgeModule协议。

1
2
3
4
5
6
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
@interface CalendarManager : RCTEventEmitter <RCTBridgeModule>
@end

然后在实现的部分引入RCT_EXPORT_MODULE();

这些都是常规操作。

这个时候先跑一下试试。。。

发现。。程序崩溃了,看一下原因,是因为没有实现supportedEvents方法。没关系,这个我们也不用惊讶,毕竟人家官方文档中都写了。那我们就补上这个代码,返回和RN同学商量好的方法名;

1
2
3
4
- (NSArray<NSString *> *)supportedEvents
{
return @[@"EventReminder"];
}

然后尝试发送一次试试看看能不能实现。

1
2
3
4
5
- (void)calendarEventReminderReceived:(NSNotification *)notification
{
NSString *eventName = notification.userInfo[@"name"];
[self sendEventWithName:@"EventReminder" body:@{@"name": eventName}];
}

结果发现还是崩溃了,这时候提示崩溃的原因就是我们这篇文章的主题

1
2
3
bridge is not set. This is probably because you've "
"explicitly synthesized the bridge in %@, even though it's inherited "
"from RCTEventEmitter.

仔细看看这个报错的信息发现是因为这个bridge为空,然后仔细看你会发现,你写的代码和官方文档的没什么区别,只能去google或者查看RN的issue,这时候你会发现你不是一个人,有人会告诉你可以在Appdelegate.m中设置rootView的bridge,跟着老大哥的写法走一遍,发现好像确实没有崩溃,但是。。。

但是。。

好像RN这边根本没有办法监听到事件。

。。。

填坑

所以这边到底要怎么来解决呢??

实际上需要的写法是,这个类必须要使用单例,而且需要用比较优雅的方式实现单例,也就是说也要考虑到alloc init的同学,所以要重写allocWithZone:的方法。

ok废话不多说,直接在.m文件中重写这个方法

1
2
3
4
5
6
7
8
9
+(id)allocWithZone:(NSZone *)zone
{
static RNBridge *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [super allocWithZone:zone];
});
return sharedInstance;
}

再运行,你就会发现世界是多么的美好。

以上就是这个坑的解决方案,如果有大佬有更好的解决方案可以留言或者私信我。