iOS/CloudKitCatalog/CloudKitCatalog/FetchRecordChangesSample.swift
/* |
Copyright (C) 2016 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
This file contains a class which manages an in-memory cache of changed records from the result of |
a FetchRecordChangesOperation, as well as a code sample demonstrating how to fetch record changes |
and paginate through the results on the server using the moreComing property on the response. |
*/ |
import CloudKit |
class ChangedRecords { |
var changeToken: CKServerChangeToken? |
private var results: Results = Results(alwaysShowAsList: true) |
private var recordsByID: [CKRecordID: CKRecord] = [:] |
func getRecordByID(recordID: CKRecordID) -> CKRecord? { |
return recordsByID[recordID] |
} |
func getRecords() -> Results { |
return results |
} |
func addRecord(record: CKRecord) { |
results.items.append(record) |
recordsByID[record.recordID] = record |
results.added.insert(results.items.count - 1) |
} |
private func indexOfRecordByRecordID(recordID: CKRecordID) -> Int? { |
return results.items.indexOf { result in |
if let result = result as? CKRecord { |
return result.recordID == recordID |
} else { |
return false |
} |
} |
} |
func markRecordAsModified(record: CKRecord) { |
if let index = indexOfRecordByRecordID(record.recordID) { |
results.modified.insert(index) |
} |
} |
func markRecordAsDeleted(recordID: CKRecordID) { |
if let index = indexOfRecordByRecordID(recordID) { |
results.deleted.insert(index) |
} |
} |
private func removeDeletedRecords() { |
for index in results.deleted { |
let record = results.items.removeAtIndex(index) as! CKRecord |
recordsByID[record.recordID] = nil |
} |
} |
func setMoreComing(bool: Bool) { |
results.moreComing = bool |
} |
func removeChanges() { |
removeDeletedRecords() |
results.added = [] |
results.deleted = [] |
results.modified = [] |
} |
func reset() { |
changeToken = nil |
results.reset() |
recordsByID = [:] |
} |
} |
class FetchRecordChangesSample: CodeSample { |
init() { |
super.init( |
title: "CKFetchChangesOperation", |
className: "CKFetchChangesOperation", |
methodName: ".init(recordZoneID:previousServerChangeToken:)", |
descriptionKey: "Sync.FetchRecordChanges", |
inputs: [ |
TextInput(label: "zoneName", value: "", isRequired: true), |
BooleanInput(label: "cache", value: true) |
] |
) |
listHeading = "Records:" |
} |
var recordCache = [CKRecordZoneID: ChangedRecords]() |
override func run(completionHandler: (Results, NSError!) -> Void) { |
if let zoneName = data["zoneName"] as? String, shouldCache = data["cache"] as? Bool { |
let zoneID = CKRecordZoneID(zoneName: zoneName, ownerName: CKOwnerDefaultName) |
var cache = recordCache[zoneID] |
if cache == nil { |
cache = ChangedRecords() |
recordCache[zoneID] = cache |
} |
cache!.removeChanges() |
if !cache!.results.moreComing && !shouldCache { |
cache!.reset() |
} |
var changeToken: CKServerChangeToken? = nil |
if let token = cache!.changeToken where shouldCache || cache!.results.moreComing { |
changeToken = token |
} |
let operation = CKFetchRecordChangesOperation(recordZoneID: zoneID, previousServerChangeToken: changeToken) |
operation.desiredKeys = [ "name", "location" ] |
operation.resultsLimit = 2 |
operation.recordChangedBlock = { |
(record) in |
if let cachedRecord = cache!.getRecordByID(record.recordID) { |
for key in record.allKeys() { |
cachedRecord.setObject(record.objectForKey(key), forKey: key) |
} |
cache!.markRecordAsModified(cachedRecord) |
} else { |
cache!.addRecord(record) |
} |
} |
operation.recordWithIDWasDeletedBlock = { |
(recordID) in |
cache!.markRecordAsDeleted(recordID) |
} |
operation.fetchRecordChangesCompletionBlock = { |
(changeToken, nsData, nsError) in |
if nsError == nil { |
cache!.changeToken = changeToken |
cache!.setMoreComing(operation.moreComing) |
} |
completionHandler(cache!.getRecords(),nsError) |
} |
operation.start() |
} |
} |
} |
Copyright © 2016 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2016-09-13