CloudKit中CKNotification和CKQueryNotification有什么区别?

时间:2017-03-11 09:45:18

标签: ios swift cloudkit

有时当我在第一台设备上执行更改(例如添加40条记录)时,我会在第二台设备上获得40 CKQueryNotifications

虽然我可以将CKQueryNotifications标记为已读,但我无法将其标记为已读CKNotifications。为什么?每次发布后,他们总会回到我的设备上。为什么呢?

如何获取待处理通知?

var serverChangeToken: CKServerChangeToken? {
    return UserDefaults(suiteName: SharedGroupName)?.object(forKey: "a") as? CKServerChangeToken
}

func fetchPendingNotifications(notifications: [CKNotification] = [], completion: ErrorHandler? = nil) {

    var queryNotifications = notifications

    let operation = CKFetchNotificationChangesOperation(previousServerChangeToken: serverChangeToken)
    let operationQueue = OperationQueue()

    operation.notificationChangedBlock = { notification in

        print("+++++ \(notification)")
        queryNotifications.append(notification)
    }

    operation.fetchNotificationChangesCompletionBlock = { token, error in

        if let token = token {

            UserDefaults(suiteName: SharedGroupName)?.set(NSKeyedArchiver.archivedData(withRootObject: token), forKey: "a")
            UserDefaults(suiteName: SharedGroupName)?.synchronize()
        }

        if error == nil && operation.moreComing {
            self.fetchPendingNotifications(notifications: queryNotifications, completion: completion)
        } else {
            self.perform(queryNotifications: queryNotifications, completion: completion)
        }
    }

    operationQueue.addOperation(operation)
}

如何将通知标记为已读?

func perform(queryNotifications: [CKNotification], completion: ErrorHandler? = nil) {

    var currentQueryNotifications = queryNotifications

    if let queryNotification = currentQueryNotifications.first {

        currentQueryNotifications.removeFirst()

        let operation = CKMarkNotificationsReadOperation(notificationIDsToMarkRead: [queryNotification.notificationID!])
        operation.markNotificationsReadCompletionBlock = { _, _ in

            print("marked as read")
            self.perform(queryNotifications: currentQueryNotifications, completion: completion)
        }

        OperationQueue().addOperation(operation)

    } else {

        completion?(nil)
    }
}

控制台上的输出是什么?

+++++ , containerIdentifier=iCloud.pl.blueworld.fieldservice, badge=0>
+++++ , containerIdentifier=iCloud.pl.blueworld.fieldservice, badge=0>
+++++ , containerIdentifier=iCloud.pl.blueworld.fieldservice, badge=0>
+++++ , containerIdentifier=iCloud.pl.blueworld.fieldservice, badge=0>
+++++ , containerIdentifier=iCloud.pl.blueworld.fieldservice, badge=0>
+++++ , containerIdentifier=iCloud.pl.blueworld.fieldservice, badge=0>
+++++ , containerIdentifier=iCloud.pl.blueworld.fieldservice, badge=0>
+++++ , containerIdentifier=iCloud.pl.blueworld.fieldservice, badge=0>
+++++ , containerIdentifier=iCloud.pl.blueworld.fieldservice, badge=0>
+++++ , containerIdentifier=iCloud.pl.blueworld.fieldservice, badge=0>
+++++ , containerIdentifier=iCloud.pl.blueworld.fieldservice, badge=0>
+++++ , containerIdentifier=iCloud.pl.blueworld.fieldservice, badge=0>
+++++ , containerIdentifier=iCloud.pl.blueworld.fieldservice, badge=0>
+++++ , containerIdentifier=iCloud.pl.blueworld.fieldservice, badge=0>
marked as read
marked as read
marked as read
marked as read
marked as read
marked as read
marked as read
marked as read
marked as read
marked as read
marked as read
marked as read
marked as read
marked as read

1 个答案:

答案 0 :(得分:1)

关于为什么读取通知一直出现,文档直接与WWDC视频相矛盾。 Apple Docs清楚地说(强调增加):

  

如果使用a将一个或多个通知标记为已读   CKMarkNotificationsReadOperation对象,那些通知不是   返回,即使您为previousServerChangeToken指定了nil。

然而,WWDC 2014视频231(Advanced Cloudkit)明确表示已删除阅读通知并且始终已返回,因此用户的其他设备还能看到他们。演示者甚至举例说明了一个突出显示所有设备上的大型交易的应用程序,一旦任何设备将通知标记为已读,任何其他设备都应该看到"读取"通知并禁用突出显示。为此,他们必须能够仔细阅读标记为"阅读的通知。"

因此,我们必须考虑两个独立的通知属性:

  • 读取/未读状态:告诉我们用户的任何设备是否已看到此通知。
  • 服务器更改令牌:告诉我们我们在每个特定设备上查看了哪些通知。

将您收到的更改标记保存在fetch的完成块中,并将其传递给后续提取。这是确保设备只能看到" new"的通知的唯一方法。它。使用已读/未读状态来了解用户是否已在其他设备上对该事件执行操作。