React Native iOS端OneSignal后台通知TestFlight部署异常问题
我按照OneSignal官方指南配置了React Native应用的后台通知。通过Xcode直接安装到设备时,后台通知正常工作;但归档构建后从TestFlight安装时,虽然能收到推送通知,但我添加的emitNotificationEvent事件完全没触发。用Xcode设备控制台排查发现,TestFlight构建里NotificationExtensionModule.m的_instance是空的。
备注
- Xcode版本:13.4
- 两种安装方式都能正常接收推送通知
- 上传TestFlight只增加了构建版本号,应用版本号保持不变
- 已尝试清理构建文件夹、重新安装Pods,问题依旧
以下是相关代码片段:
AppDelegate.h
#import <Foundation/Foundation.h> #import <React/RCTBridgeDelegate.h> #import <UIKit/UIKit.h> #import <UserNotifications/UserNotifications.h> @interface AppDelegate : UIResponder <UIApplicationDelegate,RCTBridgeDelegate,UNUserNotificationCenterDelegate> @property (nonatomic, strong) UIWindow *window; @end
AppDelegate.m
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { //access NotificationServiceExtensionModule emitNotificationEvent method [NotificationServiceExtensionModule.sharedInstance emitNotificationEvent:userInfo ]; completionHandler(UIBackgroundFetchResultNoData); }
NotificationServiceExtensionModule.h
#import <foundation/Foundation.h> // NotificationServiceExtensionModule.h #import <React/RCTBridgeModule.h> #import <React/RCTEventEmitter.h> @interface NotificationServiceExtensionModule : RCTEventEmitter <RCTBridgeModule> + (NotificationServiceExtensionModule*) sharedInstance; - (void)emitNotificationEvent:(NSDictionary *)userInfo; @end
NotificationServiceExtensionModule.m
#import <Foundation/Foundation.h> // NotificationServiceExtensionModule.m #import "NotificationServiceExtensionModule.h" @implementation NotificationServiceExtensionModule static NotificationServiceExtensionModule* _instance = nil; +(NotificationServiceExtensionModule*) sharedInstance { // @synchronized( _instance ) { // if( !_instance ) { // _instance = [[NotificationServiceExtensionModule alloc] init]; // } // } return _instance; // this returns null when installed from TestFlight. } // To export a module named NotificationServiceExtensionModule RCT_EXPORT_MODULE(); - (NSArray<NSString *> *)supportedEvents { NSLog(@"Supported EVENTS__________________________"); _instance = self; return @[@"NotificationEvent"]; } - (void)emitNotificationEvent:(NSDictionary *)userInfo { NSString *eventName = userInfo[@"custom"][@"a"]; [self sendEventWithName:@"NotificationEvent" body:@{ "notificationPayload": eventName}]; } @end
问题原因及解决方案
核心原因
TestFlight构建开启了App Thinning/bitcode,或Release模式下的编译优化导致React Native模块初始化时机延迟,supportedEvents方法还未被调用时,AppDelegate就已经调用了sharedInstance,此时_instance还未赋值,返回空指针。另外你的单例实现没有主动初始化逻辑,完全依赖supportedEvents的赋值,进一步放大了这个问题。
具体修复方案
修复单例初始化逻辑
改成线程安全的懒加载初始化,确保第一次调用sharedInstance时就能创建实例,不再依赖supportedEvents:+(NotificationServiceExtensionModule*) sharedInstance { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [[NotificationServiceExtensionModule alloc] init]; }); return _instance; }延迟调用事件发送
在AppDelegate中给React Native桥接留足初始化时间,避免提前调用空实例:- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NotificationServiceExtensionModule *module = [NotificationServiceExtensionModule sharedInstance]; if (module != nil) { [module emitNotificationEvent:userInfo]; } }); completionHandler(UIBackgroundFetchResultNoData); }调整Release模式编译优化
进入Xcode的Target设置,找到Build Settings->Optimization Level,将Release模式下的优化暂时改为None [-O0]测试。如果问题解决,再逐步调整到合适的优化等级,避免编译器误优化_instance的赋值逻辑。验证Extension配置
确保Notification Service Extension的Bundle ID是主App Bundle ID的合法后缀(比如.notification-service),且在TestFlight构建中未被App Thinning忽略。可以在归档分发时,确认Extension被包含在构建包内。
内容的提问来源于stack exchange,提问作者Shamique

