【问题标题】:Why userNotificationCenter didReceive is not fired?为什么 userNotificationCenter didReceive 没有被解雇?
【发布时间】:2018-11-24 16:44:18
【问题描述】:

这是我的代码的一部分。我想使用UNUserNotificationCenterUNUserNotificationCenterDelegate 来处理通知事件。

此代码在应用处于前台状态时捕获通知事件。但是"didReceive" 不会因为后台状态而被触发。

func application(_ application: UIApplication,
                         didFinishLaunchingWithOptions launchOptions:
            [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
            UNUserNotificationCenter.current().delegate = self
    application.registerForRemoteNotifications()
    return true
    }    
        func userNotificationCenter(_ center: UNUserNotificationCenter,
                                    willPresent notification: UNNotification,
                                    withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
        {
            print("willPresent") /// This works
            completionHandler([.alert, .badge, .sound])
        }
        func userNotificationCenter(_ center: UNUserNotificationCenter,
                                    didReceive response: UNNotificationResponse,
                                    withCompletionHandler completionHandler: @escaping () -> Void) {
            print("didReceive") /// This doesn't work
            completionHandler()
        }

但如果我不使用UNUserNotificationCenter.current().delegate = self,委托方法会在后台正确触发。

func application(_ application: UIApplication,
                     didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping FetchCompletionHandler) {
        print("didReceiveRemoteNotification... \(userInfo)")
}

如何使用“didReceive”?我想在后台处理通知。

【问题讨论】:

    标签: ios swift push-notification unusernotificationcenter


    【解决方案1】:

    application(_:didReceiveRemoteNotification:fetchCompletionHandler:) 在应用程序接收到静默推送通知时被调用。当应用程序处于后台状态时,可以发送静默推送通知,iOS 唤醒应用程序执行用户不可见的后台处理。

    静默推送通知将 content-available 标志设置为 1。

    静默推送通知不应包含警报、徽章或声音。静默推送并不意味着对用户可见,它只是向应用程序提示新的远程内容可用。

    从推送通知负载中删除content-available 标志将导致iOS 将其作为常规通知处理。将调用用户通知中心委托方法而不是 application(_:didReceiveRemoteNotification:fetchCompletionHandler:),但您的应用程序将无法执行通知触发的后台处理。

    您可以使用this tool 验证推送通知负载的内容是否存在此类问题

    【讨论】:

    • 这似乎不是这种情况(不再):“要支持后台更新通知,请确保有效负载的 aps 字典包含值为 1 的内容可用键。如果有是与后台更新一起出现的用户可见更新,您可以根据需要在 aps 字典中设置警报、声音或徽章键。”来自developer.apple.com/library/archive/documentation/…
    【解决方案2】:

    这就是我在应用程序中处理推送通知的方式。我认为您需要实现所有这些方法以在前台和后台模式下处理所有 iOS 版本。

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    
        if #available(iOS 10.0, *) {
            let center  = UNUserNotificationCenter.current()
            center.delegate = self
            center.requestAuthorization(options: [.sound,.alert,.badge], completionHandler: { (granted, error) in
                if error == nil {
                    DispatchQueue.main.async {
                        application.registerForRemoteNotifications()
                    }
                }
            })
        }
        else {
            let notificationTypes: UIUserNotificationType = [UIUserNotificationType.alert, UIUserNotificationType.badge, UIUserNotificationType.sound]
            let pushNotificationSettings = UIUserNotificationSettings(types: notificationTypes, categories: nil)
            application.registerUserNotificationSettings(pushNotificationSettings)
            application.registerForRemoteNotifications()
        }
    
    }
    
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
        print(deviceTokenString)
    }
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("Failed to get token; error: \(error)")
    }
    
    @available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.alert,.sound])
         //do sth
    }
    
    @available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
         //do sth
    }
    
    // for iOS < 10
    func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    }
    

    【讨论】:

      【解决方案3】:

      有UNUserNotificationCenterDelegate的方法:

      • willPresent:当您的应用处于前台时,当您收到通知时会调用此方法。如果应用程序在后台,则此方法不会调用。

      • didRecieve:当用户点击通知时调用此方法。

      在后台状态下,当用户点击通知时,只会调用“didRecieve”。

      【讨论】:

        猜你喜欢
        • 2017-09-01
        • 1970-01-01
        • 2020-03-28
        • 2015-10-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多