在 iOS 11 中用 CloudKit 将通知标记为已读

Mark Notifications as Read in iOS 11 with CloudKit

我有一个使用 CloudKit 的应用程序,在 iOS 11 之前一切正常。

在以前的 iOS 版本中,我使用 CKQuerySubscriptionNSPredicate 来在用户更改特定 table 时接收通知,匹配 NSPredicate属性。

这样做之后,每当服务器发送通知时,我都会遍历它们,获取它的更改,然后将它们标记为 READ,这样我会再次解析它们(保存 serverToken) .

现在在 iOS 11 中,Xcode 通知我这些代表是 deprecated,我应该更改它们,但这是我遇到问题的地方 - 我不能iOS 11.

弄清楚如何以未弃用的方式进行操作

这是我的代码:

正在保存订阅

fileprivate func setupCloudkitSubscription() {
    let userDefaults = UserDefaults.standard
    let predicate = NSPredicate(format: /*...*/) // predicate here
    let subscription = CKQuerySubscription(recordType: "recordType", predicate: predicate, subscriptionID: "tablename-changes", options: [.firesOnRecordUpdate, .firesOnRecordCreation])
    let notificationInfo = CKNotificationInfo()
    notificationInfo.shouldSendContentAvailable = true // if true, then it will push as a silent notification
    subscription.notificationInfo = notificationInfo

    let publicDB = CKContainer.default().publicCloudDatabase
    publicDB.save(subscription) { (subscription, err) in
        if err != nil {
            print("Failed to save subscription:", err ?? "")
            return
        } 
    }       
}

检查未决通知

fileprivate func checkForPendingNotifications() {
    let serverToken = UserDefaults.standard.pushNotificationsChangeToken
    let operation = CKFetchNotificationChangesOperation(previousServerChangeToken: serverToken)

    var notificationIDsToMarkRead = [CKNotificationID]()
    operation.notificationChangedBlock = { (notification) -> Void in
        if let notificationID = notification.notificationID {
            notificationIDsToMarkRead.append(notificationID)
        }
    }
    operation.fetchNotificationChangesCompletionBlock = {(token, err) -> Void in
        if err != nil {
            print("Error occured fetchNotificationChangesCompletionBlock:", err ?? "")
            print("deleting existing token and refetch pending notifications")

            UserDefaults.standard.pushNotificationsChangeToken = nil
            return
        }
        let markOperation = CKMarkNotificationsReadOperation(notificationIDsToMarkRead: notificationIDsToMarkRead)
        markOperation.markNotificationsReadCompletionBlock  = { (notificationIDsMarkedRead: [CKNotificationID]?, operationError: Error?) -> Void in
            if operationError != nil {
                print("ERROR MARKING NOTIFICATIONS:", operationError ?? "")
                return
            }
        }
        let operationQueue = OperationQueue()
        operationQueue.addOperation(markOperation)
        if token != nil {
            UserDefaults.standard.pushNotificationsChangeToken = token
        }
    }
    let operationQueue = OperationQueue()
    operationQueue.addOperation(operation)
}

如您所见,上面的代码在 iOS 直到 11;

上运行完美

现在Xcode在以下几行提示警告:

let operation = CKFetchNotificationChangesOperation(previousServerChangeToken: serverToken)

警告:

'CKFetchNotificationChangesOperation' was deprecated in iOS 11.0: Instead of iterating notifications to enumerate changed record zones, use CKDatabaseSubscription, CKFetchDatabaseChangesOperation, and CKFetchRecordZoneChangesOperation

AND

let markOperation = CKMarkNotificationsReadOperation(notificationIDsToMarkRead: notificationIDsToMarkRead)

警告:

'CKMarkNotificationsReadOperation' was deprecated in iOS 11.0: Instead of iterating notifications, consider using CKDatabaseSubscription, CKFetchDatabaseChangesOperation, and CKFetchRecordZoneChangesOperation as appropriate

我尝试应用 CKDatabaseSubscription,但这样做我无法像使用 CKQuerySubscription 那样应用 NSPredicate 来过滤订阅,如果我尝试获取并标记为待处理通知 Read 它显示了这些警告。

在这种情况下,iOS 11 的最佳方法是什么?有什么提示吗?

谢谢。

因此,正如我在 openradar 错误报告上面的评论中提到的那样,可以找到 here 这是 iOS 11 中为 [ 获取更改时的一个已知问题=34=] 记录,然后将这些更改标记为已读,保存给定的标记。

因为这个问题没有真正的解决方案,因为 Apple 没有为此提供解决方法,或者在给出解决方案之前可能不会将这些委托功能标记为已弃用,我不得不走另一条路,这是以下内容:

我必须在 Private Database 中创建一个自定义 CKRecordZone,然后我必须订阅 zoneID 中的数据库更改,通过这样做,每当用户更改其中的内容时数据库所需的 push-notifications and/or silent-push-notifications 按预期触发,然后我可以解析新数据。

我的问题是我在 public 数据库中有 User Profile,所以每当用户更改与他相关的内容(姓名、简历等)时,它都会保存在 CloudKit 并且静默通知会触发用户的其他设备以更新此数据 - 我也可以使用私有数据库完美地做到这一点 - 但我的问题是其他用户可以搜索应用程序用户来关注 - 取消关注他们并且如果该数据存储在私有数据库中,一般用户搜索范围之外。

为了克服这个问题,我不得不半复制用户配置文件数据。 用户通过私有数据库获取和编辑其数据,并在保存时还更新 public 数据库中的半相关 table 以便普通用户可以搜索。

直到 Apple 允许我们像以前在 iOS 10 中那样从 public 数据库中获取更改,此解决方案暂时对我有用。