Reputation: 1835
I am new to CloudKit and have figured out CKModifyRecordsOperation
with basic cases of add/remove/delete of one CKRecord
at a time. I want to use it to pass in multiple recordsToSave
and recordIDsToDelete
. I know that I need to do a retry when error.userInfo[CKErrorRetryAfterKey]
has a value. My question is, how do I retry this operation? I am stuck figuring out how to know what records to retry. Do I have to retry all records? Which completion block can I do a retry in, or is it both?
My code is below with comments where I don't understand how to retry.
func modifyCkRecs(recsToAddOrMod: [CKRecord]?, recordIDsToDelete:[CKRecordID]?, numTries: Int) {
let ops = CKModifyRecordsOperation(recordsToSave: recsToAddOrMod, recordIDsToDelete: recordIDsToDelete)
ops.savePolicy = CKRecordSavePolicy.AllKeys
ops.perRecordCompletionBlock = { record, error in
if let error = error {
var message = error.localizedDescription
if error.code == CKErrorCode.NotAuthenticated.rawValue {
print("Not authenticated")
message = "If you want your data the same on all your Apple devices, then log into iCloud on your device and make sure the iCloud drive is turned on for this app.\nTo enable iCloud, go to Settings -> iCloud"
}
if error.code == CKErrorCode.ServiceUnavailable.rawValue {
print("Service unavailable")
}
if error.code == CKErrorCode.RequestRateLimited.rawValue {
print("Request Rate Limited")
}
if error.code == CKErrorCode.NetworkFailure.rawValue {
print("Network failure!!")
}
if error.code == CKErrorCode.InvalidArguments.rawValue {
print("Invalid Arguments!!")
}
print("Error msg: \(message)")
// if let delayTime = self.retryTime(error) {
// if numTries < CloudKitAPI.MAX_RETRY {
//
// dispatch_after(delayTime, dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)) {
// self.modifyCkRecs(????,????, numTries: numTries+1)
// }
// }
// else {
// print("WARNING: Reached MAX number of retry, giving up")
// }
// }
}
else {
print("Update was a success!")
if let updatedRec = record {
if let coreDataObj = self.convertRecToCoreData(updatedRec) {
// archive the CKRecord system fields into Core Data
coreDataObj.archiveCkMetadata(updatedRec)
// remove from queue
self.addedOrModQueue.removeValueForKey(coreDataObj.uuid)
self.saveAMQueue()
}
}
}
}
// TODO: Figure out what this block is good for
ops.modifyRecordsCompletionBlock = { savedRecords, deletedRecordIDs, error in
if let error = error {
var message = error.localizedDescription
if error.code == CKErrorCode.NotAuthenticated.rawValue {
print("Not authenticated")
message = "If you want your data the same on all your Apple devices, then log into iCloud on your device and make sure the iCloud drive is turned on for this app.\nTo enable iCloud, go to Settings -> iCloud"
}
if error.code == CKErrorCode.ServiceUnavailable.rawValue {
print("Service unavailable")
}
if error.code == CKErrorCode.RequestRateLimited.rawValue {
print("Request Rate Limited")
}
if error.code == CKErrorCode.NetworkFailure.rawValue {
print("Network failure!!")
}
if error.code == CKErrorCode.InvalidArguments.rawValue {
print("Invalid Arguments!!")
}
print("Error msg: \(message)")
// RETRY LOGIC HERE????
// SOMETHING LIKE THE ABOVE BUT WITH THESE ARGS:
// self.modifyCkRecs(recsToAddOrMod, recordIDsToDelete, numTries: numTries+1)
}
else {
// clean up the deleted queue
if let deletedRecs = deletedRecordIDs {
for deletedRecId in deletedRecs {
if let uuid = NSUUID(UUIDString: deletedRecId.recordName), let index = self.deletedQueue.indexOf(uuid) {
self.deletedQueue.removeAtIndex(index)
}
}
self.saveDQueue()
}
}
}
ops.qualityOfService = .Background
privateDB.addOperation(ops)
}
Upvotes: 1
Views: 493