上次说到了与RN交互时,RN引用原生UI组件时出现的坑,如果说上次的坑是因为没有仔细看官方文档导致的,这次的坑应该算是RN自己的问题了吧。
这次的问题是当原生端主动向RN(JS)发送请求的时候,会崩溃,报错显示
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方监听到这个广播之后就会做对应的事情。
还是一样,我们从官方文档入手,官方文档中写的内容也不多,一屏就能显示全:
example.pngok,我们也是一样,还是照着官方文档撸代码。
先写一个继承于RCTEventEmitter
的类,然后实现RCTBridgeModule
协议。
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
@interface CalendarManager : RCTEventEmitter <RCTBridgeModule>
@end
然后在实现的部分引入RCT_EXPORT_MODULE();
这些都是常规操作。
这个时候先跑一下试试。。。
发现。。程序崩溃了,看一下原因,是因为没有实现supportedEvents
方法。没关系,这个我们也不用惊讶,毕竟人家官方文档中都写了。那我们就补上这个代码,返回和RN同学商量好的方法名;
- (NSArray<NSString *> *)supportedEvents
{
return @[@"EventReminder"];
}
然后尝试发送一次试试看看能不能实现。
- (void)calendarEventReminderReceived:(NSNotification *)notification
{
NSString *eventName = notification.userInfo[@"name"];
[self sendEventWithName:@"EventReminder" body:@{@"name": eventName}];
}
结果发现还是崩溃了,这时候提示崩溃的原因就是我们这篇文章的主题
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文件中重写这个方法
+(id)allocWithZone:(NSZone *)zone
{
static RNBridge *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [super allocWithZone:zone];
});
return sharedInstance;
}
再运行,你就会发现世界是多么的美好。
以上就是这个坑的解决方案,如果有大佬有更好的解决方案可以留言或者私信我。
网友评论