上次說到了與RN交互時,RN引用原生UI組件時出現(xiàn)的坑,如果說上次的坑是因為沒有仔細看官方文檔導(dǎo)致的,這次的坑應(yīng)該算是RN自己的問題了吧。
這次的問題是當(dāng)原生端主動向RN(JS)發(fā)送請求的時候,會崩潰,報錯顯示
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,用于監(jiān)聽通知。當(dāng)原生部分需要主動跟RN進行通信的時候,就可以發(fā)出一個廣播,RN方監(jiān)聽到這個廣播之后就會做對應(yīng)的事情。
還是一樣,我們從官方文檔入手,官方文檔中寫的內(nèi)容也不多,一屏就能顯示全:

ok,我們也是一樣,還是照著官方文檔擼代碼。
先寫一個繼承于RCTEventEmitter的類,然后實現(xiàn)RCTBridgeModule協(xié)議。
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
@interface CalendarManager : RCTEventEmitter <RCTBridgeModule>
@end
然后在實現(xiàn)的部分引入RCT_EXPORT_MODULE();
這些都是常規(guī)操作。
這個時候先跑一下試試。。。
發(fā)現(xiàn)。。程序崩潰了,看一下原因,是因為沒有實現(xiàn)supportedEvents方法。沒關(guān)系,這個我們也不用驚訝,畢竟人家官方文檔中都寫了。那我們就補上這個代碼,返回和RN同學(xué)商量好的方法名;
- (NSArray<NSString *> *)supportedEvents
{
return @[@"EventReminder"];
}
然后嘗試發(fā)送一次試試看看能不能實現(xiàn)。
- (void)calendarEventReminderReceived:(NSNotification *)notification
{
NSString *eventName = notification.userInfo[@"name"];
[self sendEventWithName:@"EventReminder" body:@{@"name": eventName}];
}
結(jié)果發(fā)現(xiàn)還是崩潰了,這時候提示崩潰的原因就是我們這篇文章的主題
bridge is not set. This is probably because you've "
"explicitly synthesized the bridge in %@, even though it's inherited "
"from RCTEventEmitter.
坑
仔細看看這個報錯的信息發(fā)現(xiàn)是因為這個bridge為空,然后仔細看你會發(fā)現(xiàn),你寫的代碼和官方文檔的沒什么區(qū)別,只能去google或者查看RN的issue,這時候你會發(fā)現(xiàn)你不是一個人,有人會告訴你可以在Appdelegate.m中設(shè)置rootView的bridge,跟著老大哥的寫法走一遍,發(fā)現(xiàn)好像確實沒有崩潰,但是。。。
但是。。
好像RN這邊根本沒有辦法監(jiān)聽到事件。
。。。
填坑
所以這邊到底要怎么來解決呢??
實際上需要的寫法是,這個類必須要使用單例,而且需要用比較優(yōu)雅的方式實現(xiàn)單例,也就是說也要考慮到alloc init的同學(xué),所以要重寫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;
}
再運行,你就會發(fā)現(xiàn)世界是多么的美好。
以上就是這個坑的解決方案,如果有大佬有更好的解決方案可以留言或者私信我。