在Flutter中使用firebase_messaging插件时设置UNNotificationCenterDelegate的冲突问题
在Flutter中使用firebase_messaging插件时设置UNNotificationCenterDelegate的冲突问题
哥们我太懂你这个坑了!我之前做Flutter推送的时候也踩过一模一样的雷——当你自己在AppDelegate里设置了UNUserNotificationCenter的代理,还实现了didReceiveNotificationResponse方法后,是不是发现Firebase Messaging原本的通知点击逻辑突然失效了?
问题根源其实很简单
firebase_messaging插件内部已经悄悄把UNUserNotificationCenter的代理设置成了它自己的处理对象(就是你提到的FLTFirebaseMessaging相关类),当你在didFinishLaunchingWithOptions里把代理改成self时,直接把插件的代理覆盖了,插件自然收不到通知响应的回调,原有功能就崩了。
最稳妥的解决方案:代理转发
我们不用把插件的代理完全挤走,而是做个“中间商”——先保存插件的原始代理,处理完自己的自定义按钮逻辑后,再把事件转发给原始代理,这样两边的逻辑都能正常跑。
具体步骤如下:
- 先在AppDelegate里声明一个变量,用来保存插件的原始代理:
@property (nonatomic, weak) id<UNUserNotificationCenterDelegate> originalFCMNotificationDelegate;
- 在
didFinishLaunchingWithOptions里,先存下插件的代理,再把自己设为新代理:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 先保存Firebase已经设置好的原始代理 self.originalFCMNotificationDelegate = [UNUserNotificationCenter currentNotificationCenter].delegate; // 再把当前AppDelegate设为代理 [UNUserNotificationCenter currentNotificationCenter].delegate = self; // 其他初始化代码... return [super application:application didFinishLaunchingWithOptions:launchOptions]; }
- 在你的
didReceiveNotificationResponse方法里,先处理自定义按钮逻辑,再转发给原始代理:
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler { // 第一步:处理你自己的自定义动作按钮逻辑 if ([response.actionIdentifier isEqualToString:@"你的自定义按钮ID"]) { // 通过MethodChannel给Flutter侧发送事件 FlutterMethodChannel *notificationChannel = [FlutterMethodChannel methodChannelWithName:@"com.your.app/notification_actions" binaryMessenger:self.flutterViewController]; [notificationChannel invokeMethod:@"handleCustomAction" arguments:@{ @"actionId": response.actionIdentifier, @"notificationData": response.notification.request.content.userInfo }]; } // 第二步:把事件转发给Firebase的原始代理,保证插件原有逻辑正常运行 if (self.originalFCMNotificationDelegate && [self.originalFCMNotificationDelegate respondsToSelector:@selector(userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:)]) { [self.originalFCMNotificationDelegate userNotificationCenter:center didReceiveNotificationResponse:response withCompletionHandler:completionHandler]; } else { // 万一原始代理不存在,也必须调用completionHandler,否则会导致App卡死 completionHandler(); } }
- 如果你还需要处理前台通知展示的逻辑,记得对
willPresentNotification方法也做同样的转发:
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler { // 这里可以加自己的前台通知处理逻辑(比如自定义展示样式) // 转发给Firebase原始代理 if (self.originalFCMNotificationDelegate && [self.originalFCMNotificationDelegate respondsToSelector:@selector(userNotificationCenter:willPresentNotification:withCompletionHandler:)]) { [self.originalFCMNotificationDelegate userNotificationCenter:center willPresentNotification:notification withCompletionHandler:completionHandler]; } else { // 默认展示选项:横幅+提示音 completionHandler(UNNotificationPresentationOptionBanner | UNNotificationPresentationOptionSound); } }
最后别忘了在Flutter侧注册MethodChannel的监听,这样iOS端发过来的自定义动作事件才能被Flutter接收处理哦~
备注:内容来源于stack exchange,提问作者Thijs
相关产品推荐
相关产品推荐

