iOS - 推送通知未按预期响应

iOS - Push Notifications not responding as expected

我已经创建了一个 CloudKit 对特定 class 的订阅,它会在对象创建或更新时触发推送通知。

代码如下:

    // Create the predicate
let predicate = NSPredicate(format: "recordId = %@", RECORD_ID)

// Create a subscription specifying the record type, predicate and notification options
let subscription = CKQuerySubscription(recordType: "Notes", predicate: predicate, options: [.firesOnRecordUpdate, .firesOnRecordCreation])

// Create a CloudKit notification object
let notificationInfo = CKNotificationInfo()
notificationInfo.shouldBadge = true

// Set the subscriptor's notification object to the new CloudKit notification object
subscription.notificationInfo = notificationInfo

// Save the subscription to the database
let publicDatabase = CKContainer.default().publicCloudDatabase
publicDatabase.save(subscription) { (subs, err) in
    if let err = err {
        print("Failed to save subscription:", err)
        return
    }
}

订阅已成功保存在服务器中。

我想创建一个静默通知,我正在按以下方式处理通知(收到时):

    import UserNotifications

// Register for push notifications
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.requestAuthorization(options: [.badge, .alert, .sound]) { (success, err) in
    if let err = err {
        print("Failed to request oauth for notifications:", err)
    }
}
application.registerForRemoteNotifications()

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    print("didRegisterForRemoteNotificationsWithDeviceToken:", deviceToken)
}

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    print("Failed to register notifications_ error:", error)
}

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    print("------------------------")
    print("Receiving updates from the server") 

    // Convert the userInfo parameter to a CKNotification object
    let cloudKitNotification = CKNotification(fromRemoteNotificationDictionary: userInfo)

    // Get the body of the notification
    let alertBody = cloudKitNotification.alertBody
    print("alertBody:", alertBody ?? "")

    // Get the new or modified record form the CKQueryNotification object
    if cloudKitNotification.notificationType == CKNotificationType.query {
        guard let queryNotification = cloudKitNotification as? CKQueryNotification else {
            print("could not cast the query notification")
            return
        }
        let recordId = queryNotification.recordID
        print("recordId:", recordId ?? "")
    }
}

问题出在这里。

如果我正在使用该应用程序并且更新已发送到服务器,我的 didReceiveRemoteNotification 会触发并且一切正常,但是如果我的应用程序在后台运行,我的 app_notification 徽章会发生变化(增加 1)当收到推送通知但 didReceiveRemoteNotification 没有触发时。

我的问题是,当推送通知条目到达时,我该如何处理?

我在 Info.plis 文件中用 App downloads content from the networkApp downloads content in response to push notifications

设置了 Required background modes

我还注意到一件事,如果我将 notificationInfo.shouldBadge 设置为 false,我将不会收到任何推送通知。

感谢您的帮助

通知不能保证到达,特别是如果用户进入飞行模式、失去连接等。而且,即使您确实收到通知,当您的应用 运行 时,您也不能执行任何处理。这意味着您必须假设每次启动应用程序时仍有通知等待处理(那些您在不在应用程序中时收到的通知以及您从未收到任何推送通知的通知,无论出于何种原因)。

因此,当您启动该应用程序时,您需要发出 CKFetchNotificationsChangesOperation 并查找您尚未处理的新通知。

您创建 CKFetchNotificationChangesOperation 操作,并设置 notificationChangedBlock。对于从服务器中提取的每个通知,该块将被调用一次。您可以评估它是否已标记为 "read"。如果不是,则按照您通常在 didReceiveRemoteNotification.

中的方式处理它

您还可以选择在 fetchNotificationChangesCompletionBlock 中设置代码,在操作结束时从服务器获取所有通知后触发一次。