我正在运行CKFetchNotificationChangesOperation
以下拉自上次我的应用运行以来应该发送的所有更新通知。
我得到了一堆CKNotification
个对象,正如我所期望的那样,但每个CKNotification的recordFields
对象都是零。我希望它可以填充我对象的所有已更改属性。
但也许情况并非如此。
我没有指定desiredKeys
对象的CKSubscription
属性,这显然会强制CKNotification
recordFields
保存该数据。但是文档说desiredKeys
只能有3个值,而且我的对象有3个以上可以更新的值。
所以现在我在想,我只需要获取CKNotification
对象,看看它是否是更新,然后重新获取它指向的对象以检索其数据。然后,我可以对新CKRecord
与旧版本进行差异,看看有什么变化。
我是否正确理解了这一点?
答案 0 :(得分:3)
首先,您需要存储CKServerChangeToken
CKFetchNotificationChangesOperation
var notificationChangesOperation = CKFetchNotificationChangesOperation(previousServerChangeToken: previousChangeToken)
var fetchedRecordIDs:[CKRecordID]()
//we just care about inserts, we don't care about of changes of records existing in database, that's why it's enough just to save recordIDs
notificationChangesOperation.notificationChangedBlock = {notification in
let queryNotif = notification as CKQueryNotification
// println("fetched CKQueryNotification \(queryNotif)")
if (!contains(fetchedRecordIDs, queryNotif.recordID)) {
fetchedRecordIDs.append(queryNotif.recordID)
}
}
notificationChangesOperation.fetchNotificationChangesCompletionBlock = {serverChangeToken, error in
if (error) {
println("failed to fetch notification \(error)")
}
self.previousChangeToken = serverChangeToken
completionHandler(recordIDs: fetchedRecordIDs, error: error)
}
container.addOperation(notificationChangesOperation)
var previousChangeToken:CKServerChangeToken? {
get {
let encodedObjectData = NSUserDefaults.standardUserDefaults().objectForKey(SubscriptionKeys.PreviousChangeToken) as? NSData
if (encodedObjectData) {
return NSKeyedUnarchiver.unarchiveObjectWithData(encodedObjectData) as? CKServerChangeToken
}
return nil
}
set(newToken) {
if (newToken) {
println("new token \(newToken)")
NSUserDefaults.standardUserDefaults().setObject(NSKeyedArchiver.archivedDataWithRootObject(newToken), forKey:SubscriptionKeys.PreviousChangeToken)
}
}
}
然后在CKFetchNotificationChangesOperation
的下一次调用中传递它。然后,此操作将为您提供自上次请求以来的更新。 CKNotification
(CKQueryNotification
)为您提供CKRecordID
个对象,而不是CKRecord
。
因此,您需要使用CKRecord
重新获取这些ID的所有CKFetchRecordsOperation
,并相应地更新模型对象。
func queryMessagesWithIDs(IDs:[CKRecordID], completionHandler: ([CKRecord]!, NSError!) -> Void) {
var fetchRecordsOperation = CKFetchRecordsOperation(recordIDs: IDs)
var messages:[CKRecord]()
fetchRecordsOperation.perRecordCompletionBlock = {record, recordID, error in
if (!error) {
messages.append(record)
} else {
println("failed to get message with ID \(recordID.recordName)")
}
}
fetchRecordsOperation.fetchRecordsCompletionBlock = {_, error in
if (error) {
println(error)
} else {
messages.sort{$0.creationDate.compare($1.creationDate) == NSComparisonResult.OrderedAscending}
}
dispatch_async(dispatch_get_main_queue(), {completionHandler(messages, error)})
}
publicDatabase.addOperation(fetchRecordsOperation)
}
答案 1 :(得分:1)
在iOS 11中,不推荐使用CKFetchNotificationChangesOperation,标题为Apple建议:
"使用CKDatabaseSubscription,CKFetchDatabaseChangesOperation和CKFetchRecordZoneChangesOperation"
,而不是迭代通知以枚举更改的记录区域。