3

CKFetchNotificationChangesOperationアプリを最後に実行してから送信されたと思われるすべての更新通知をプルダウンするために を実行しています。

予想どおり、たくさんのCKNotificationオブジェクトを取得していますがrecordFields、これらの CKNotification のすべてのオブジェクトは nil です。オブジェクトの変更されたすべての属性が入力されることを期待していました。しかし、そうではないかもしれません。

desiredKeysオブジェクトの属性を指定していないため、明らかにそのデータを保持するようにCKSubscription強制されます。CKNotification recordFieldsしかし、ドキュメントによるdesiredKeysと、値は3つしか持てず、私のオブジェクトには更新可能な値が3つ以上あります。

CKNotificationオブジェクトを取得し、それが更新かどうかを確認し、それが指しているオブジェクトを再フェッチしてデータを取得する必要があると考えています。次に、新しいCKRecordものと古いものを比較して、変更点を確認します。

私はこれを正しく理解していますか?

4

2 に答える 2

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)
}
于 2014-07-20T03:53:22.880 に答える