我有以下情況。
2 個相同的 react-native 應用程式(僅對 bundleId、應用程式圖示等不同)結構如下:
->專案結構
我的目標是當用戶收到或點擊推送通知時(假設應用程式處于前臺并且應用程式已完成啟動),通過橋從本機端向 JS 層發出事件。在第一個應用程式上,當我使用命令向我的模擬器觸發推送通知時,以下代碼按預期作業xcrun simctl push <device-id> <bundleId> <filename>.apns,第二個應用程式立即崩潰并出現以下錯誤:
Thread 1: "Error when sending event: pushDelivered with body: <the string passed as body>. RCTCallableJSModules is not set. This is probably because you've explicitly synthesized the RCTCallableJSModules in CustomEventsEmitter, even though it's inherited from RCTEventEmitter."
-> xcode 視圖
這是引發斷言的 RCTEventEmitter 的 sendEventWithName 的代碼實作。
我不知道這是否與我的實施有關。在 2 個應用程式中,有一個像魅力一樣作業,另一個 ??。任何人都可以幫我找到代碼中的問題嗎?應該是橋的問題?
我已經嘗試過多次重新安裝 pod、清理專案和重建。該代碼適用于專案A,而不適用于專案B ..我無法弄清楚原因
AppDelegate.h
#import <React/RCTBridgeDelegate.h>
#import <React/RCTBridgeModule.h>
#import <UIKit/UIKit.h>
#import <UserNotifications/UserNotifications.h>
#import <UserNotifications/UNUserNotificationCenter.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate, RCTBridgeModule, UNUserNotificationCenterDelegate>
@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, strong) NSDictionary *receivedNotificationUserInfo;
@end
AppDelegate.mm
#import "AppDelegate.h"
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <React/RCTAppSetupUtils.h>
#import <UserNotifications/UserNotifications.h>
#import "CustomEventsEmitter.h"
@implementation AppDelegate
bool hasFinishedLaunching = false;
CustomEventsEmitter *customEventsEmitter = NULL;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
hasFinishedLaunching = true;
customEventsEmitter = [CustomEventsEmitter allocWithZone: nil];
RCTAppSetupPrepareApp(application);
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
NSDictionary *initProps = [self prepareInitialProps];
UIView *rootView = RCTAppSetupDefaultRootView(bridge, @"MyAppName", initProps);
if (@available(iOS 13.0, *)) {
rootView.backgroundColor = [UIColor systemBackgroundColor];
} else {
rootView.backgroundColor = [UIColor whiteColor];
}
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
// Define UNUserNotificationCenter
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
return YES;
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
#else
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}
-(void)applicationDidBecomeActive:(UIApplication *)application
{
application.applicationIconBadgeNumber = 0;
}
// The method will be called on the delegate when the user responded to the notification by opening
// the application, dismissing the notification or choosing a UNNotificationAction. The delegate
// must be set before the application returns from applicationDidFinishLaunching:.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)(void))completionHandler {
NSLog(@"didReceiveNotificationResponse response: %@", response);
NSDictionary *userInfo = response.notification.request.content.userInfo;
if (userInfo[@"_od"]){
// if no listeners has been registered yet, store the value
// this is the case when the notification was clicked from closed app
if(![customEventsEmitter hasListeners]) {
// handle this case ...
}
// if listeners has been registered, emit an event
// this is the case when the notification was clicked from foreground app
else {
[self emitPushTappedEvent:userInfo[@"_od"]];
}
}
if (completionHandler != nil) {
completionHandler();
}
}
//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
NSDictionary *userInfo = notification.request.content.userInfo;
NSLog(@"User Info : %@", userInfo);
[self emitPushDeliveredEvent:userInfo[@"_od"]];
completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
}
-(void)emitPushDeliveredEvent:(NSString*)value {
NSLog(@"emitPushDeliveredEvent called");
[customEventsEmitter sendEventWithName:@"pushDelivered" body:value];
}
-(void)emitPushTappedEvent:(NSString*)value {
NSLog(@"emitPushTappedEvent called");
[customEventsEmitter sendEventWithName:@"pushTapped" body:value];
}
@end
這是 CustomEventsEmitter 檔案:
CustomEventsEmitter.h
#ifndef CustomEventsEmitter_h
#define CustomEventsEmitter_h
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
@interface CustomEventsEmitter : RCTEventEmitter <RCTBridgeModule>
- (void)sendEventName:(NSString *)eventName body:(id)body;
- (bool)hasListeners;
@end
#endif
CustomEventsEmitter.m
#import "CustomEventsEmitter.h"
@implementation CustomEventsEmitter
{
bool hasListeners;
}
RCT_EXPORT_MODULE(CustomEventsEmitter);
(id)allocWithZone:(NSZone *)zone {
static CustomEventsEmitter *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [super allocWithZone:zone];
});
return sharedInstance;
}
- (NSArray<NSString *> *)supportedEvents {
return @[@"pushDelivered", @"pushTapped"];
}
// Will be called when this module's first listener is added.
-(void)startObserving {
hasListeners = YES;
// Set up any upstream listeners or background tasks as necessary
}
// Will be called when this module's last listener is removed, or on dealloc.
-(void)stopObserving {
hasListeners = NO;
// Remove upstream listeners, stop unnecessary background tasks
}
-(bool)hasListeners {
return hasListeners;
}
- (void)sendEventName:(NSString *)eventName body:(id)body {
if (hasListeners) {
NSLog(@"CustomEventsEmitter sendEventName emitting event: %@", eventName);
[self sendEventWithName:eventName body:body];
} else {
NSLog(@"CustomEventsEmitter sendEventName called without listeners: %@", eventName);
}
}
@end
請幫助我理解
uj5u.com熱心網友回復:
哦,我已經解決了!這是我的一個錯誤。
AppModule 沒有正確呼叫 CustomEventsEmitter 的方法。像下面這樣更改代碼會使事件通過 RN 橋正確發出
-(void)emitPushDeliveredEvent:(NSString*)value {
NSLog(@"emitPushDeliveredEvent called");
[customEventsEmitter sendEventName:@"pushDelivered" body:value];
//[customEventsEmitter sendEventWithName:@"pushDelivered" body:value];
}
-(void)emitPushTappedEvent:(NSString*)value {
NSLog(@"emitPushTappedEvent called");
[customEventsEmitter sendEventName:@"pushTapped" body:value];
//[customEventsEmitter sendEventWithName:@"pushTapped" body:value];
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/513018.html
