SwiftUI应用前台无法显示Push Notifications求助
SwiftUI应用前台无法显示推送通知问题
问题详情
- SwiftUI应用在后台模式下可正常接收推送通知,但前台模式时通知完全不显示。
- 已查阅资料并实现
willPresent notification: UNNotification方法,但问题仍未解决。 - 使用环境:Xcode 14.3、iOS 16.5
应用通知设置

现有App Delegate代码
class AppDelegate: NSObject, UIApplicationDelegate { let gcmMessageIDKey = "gcm.message_id" func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { FirebaseApp.configure() IQKeyboardManager.shared.enable = true /// code for push notifications Messaging.messaging().delegate = self if #available(iOS 10.0, *) { // For iOS 10 display notification (sent via APNS) UNUserNotificationCenter.current().delegate = self let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] UNUserNotificationCenter.current().requestAuthorization( options: authOptions, completionHandler: {_, _ in }) } else { let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil) application.registerUserNotificationSettings(settings) } application.registerForRemoteNotifications() return true } /// code for notifications func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { if let messageID = userInfo[gcmMessageIDKey] { Helper.shared.printDebug("Message ID: \(messageID)") } Helper.shared.printDebug(userInfo) DispatchQueue.main.asyncAfter(deadline: .now() + 1) { if userInfo["other_data"] as? String == "Request Notification" { NotificationCenter.default.post(name: Notification.Name("request_notification"), object: nil, userInfo: userInfo) } else { NotificationCenter.default.post(name: Notification.Name("message_notification"), object: nil, userInfo: userInfo) } } completionHandler(UIBackgroundFetchResult.newData) } } /// code for push notifications extension AppDelegate: MessagingDelegate { func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { let deviceToken:[String: String] = ["token": fcmToken ?? ""] Helper.shared.printDebug("Device token: \(deviceToken)") // This token can be used for testing notifications on UserDefaults.standard.set(fcmToken, forKey: UserDefaultEnum.deviceId.rawValue) } } @available(iOS 10, *) extension AppDelegate : UNUserNotificationCenterDelegate { // Receive displayed notifications for iOS 10 devices. func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { let userInfo = notification.request.content.userInfo if let messageID = userInfo[gcmMessageIDKey] { Helper.shared.printDebug("Message ID: \(messageID)") } Helper.shared.printDebug(userInfo) // Change this to your preferred presentation option completionHandler([[.banner, .badge, .sound]]) } func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { Helper.shared.printDebug(deviceToken) } func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { Helper.shared.printDebug(error.localizedDescription) } func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let userInfo = response.notification.request.content.userInfo if let messageID = userInfo[gcmMessageIDKey] { Helper.shared.printDebug("Message ID from userNotificationCenter didReceive: \(messageID)") } Helper.shared.printDebug(userInfo) DispatchQueue.main.asyncAfter(deadline: .now() + 1) { if userInfo["other_data"] as? String == "Request Notification" { NotificationCenter.default.post(name: Notification.Name("request_notification"), object: nil, userInfo: userInfo) } else { NotificationCenter.default.post(name: Notification.Name("message_notification"), object: nil, userInfo: userInfo) } } completionHandler() } }
排查与修复建议
修正
willPresent方法的completionHandler参数
当前代码传递的是嵌套数组[[.banner, .badge, .sound]],格式错误,应改为单个数组:completionHandler([.banner, .badge, .sound])iOS 14及以上推荐使用
.banner,但需确保推送payload包含alert字段,否则即使设置也不会展示通知。确认UNUserNotificationCenter代理绑定正确性
尝试在主线程中设置代理,避免启动时异步问题导致代理未绑定:if #available(iOS 10.0, *) { DispatchQueue.main.async { UNUserNotificationCenter.current().delegate = self } // ... 其余权限请求代码 }检查推送Payload格式
如果使用FCM推送,必须确保payload包含notification字段(而非仅data字段),示例格式如下:{ "notification": { "title": "通知标题", "body": "通知内容" }, "data": { "other_data": "Request Notification" }, "to": "你的设备FCM Token" }仅传递
data字段时,前台不会自动弹出通知,需手动处理展示逻辑。验证通知权限状态
在权限请求的回调中添加日志,确认用户是否授予了通知权限:UNUserNotificationCenter.current().requestAuthorization( options: authOptions, completionHandler: { granted, error in Helper.shared.printDebug("通知权限授予:\(granted),错误信息:\(error?.localizedDescription ?? "无")") })确认AppDelegate与SwiftUI应用的关联
检查@main入口结构体是否正确使用UIApplicationDelegateAdaptor关联AppDelegate:@main struct YourAppName: App { @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate var body: some Scene { WindowGroup { ContentView() } } }
内容的提问来源于stack exchange,提问作者Taimoor Arif
相关产品推荐
相关产品推荐

