Xcode 11升级至Xcode 13后点击通知时Notification Delegates未被调用问题
解决方案:Xcode 13升级后通知代理未触发的问题
核心原因
iOS 13+ 引入了Scene生命周期,系统默认会将通知相关的回调分发到SceneDelegate,但你的项目基于旧版Xcode创建(无SceneDelegate),导致回调找不到接收方,所以代理方法没被调用。
方法一:移除Scene配置,回归纯AppDelegate生命周期
这是最直接的适配方式,适合不想引入SceneDelegate的项目:
- 打开项目的
Info.plist文件,找到并删除UIApplicationSceneManifest整个字典项(这是Scene模式的核心配置) - 确保
AppDelegate中正确配置通知代理,并且在启动时就完成设置:func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // 请求通知权限 let center = UNUserNotificationCenter.current() center.requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in if let error = error { print("通知权限请求失败:\(error.localizedDescription)") } } // 关键:将通知代理绑定到AppDelegate center.delegate = self // 注册远程通知(如果使用APNs) application.registerForRemoteNotifications() return true } - 让
AppDelegate遵循UNUserNotificationCenterDelegate协议,并实现点击通知的核心回调:extension AppDelegate: UNUserNotificationCenterDelegate { // 前台收到通知时的回调 func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { completionHandler([.alert, .sound, .badge]) } // 点击通知后的核心回调(重点!) func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { // 这里处理点击通知后的业务逻辑 print("用户点击了通知:\(response.notification.request.content.userInfo)") completionHandler() } // 远程通知到达时的回调(可选) func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { print("收到远程通知:\(userInfo)") completionHandler(.newData) } }
方法二:保留Scene配置,添加SceneDelegate处理通知
如果你的项目需要适配多窗口等Scene特性,可以添加SceneDelegate来接管通知回调:
- 创建新的
SceneDelegate.swift文件,实现基础配置和通知代理:import UIKit class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let _ = (scene as? UIWindowScene) else { return } // 将通知代理绑定到SceneDelegate UNUserNotificationCenter.current().delegate = self } } extension SceneDelegate: UNUserNotificationCenterDelegate { // 前台收到通知 func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { completionHandler([.alert, .sound, .badge]) } // 点击通知 func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { print("用户点击通知:\(response.notification.request.content.userInfo)") completionHandler() } } - 在
Info.plist的UIApplicationSceneManifest->UISceneConfigurations->Default Configuration中,确保UISceneDelegateClassName的值设置为$(PRODUCT_MODULE_NAME).SceneDelegate(自动关联你的SceneDelegate类)
额外检查项
- 确认用户已授权通知权限:可以在系统设置→你的App→通知中查看是否开启了允许通知
- 测试远程通知时,确保推送payload包含
alert字段(否则通知不会展示),后台推送需添加content-available: 1 - 确保通知代理的设置时机足够早:必须在启动阶段完成绑定,不能延迟到后续页面加载时设置
内容的提问来源于stack exchange,提问作者Krishna Yadav
相关产品推荐
相关产品推荐

