3

我正在运行 aCKFetchNotificationChangesOperation以删除自上次运行我的应用程序以来应该发送的所有更新通知。

CKNotification正如我所料,我得到了一堆对象,但是recordFields这些 CKNotification 中的每一个的对象都是零。我希望它填充我的对象的所有更改的属性。但也许事实并非如此。

我没有指定对象的desiredKeys属性CKSubscription,这显然会强制CKNotification recordFields保存该数据。但是文档说desiredKeys只能有 3 个值,而我的对象有很多超过 3 个可以更新的值。

所以现在我在想,我只需要获取CKNotification对象,看看它是否是更新,然后重新获取它指向的对象以检索其数据。然后我可以对CKRecord新旧版本进行比较,看看有什么变化。

我是否正确理解这一点?

4

2 回答 2

3

首先,您需要存储CKServerChangeTokenCKFetchNotificationChangesOperation

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 重新获取所有 s,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)
}
于 2014-07-20T03:53:22.880 回答
1

CKFetchNotificationChangesOperation is deprecated in iOS 11, in the header Apple suggest:

"Instead of iterating notifications to enumerate changed record zones, use CKDatabaseSubscription, CKFetchDatabaseChangesOperation, and CKFetchRecordZoneChangesOperation"

于 2015-04-18T09:59:30.010 回答