This app uses CloudKit for record storage and Core Data on the local device. Records created locally are saved to Core Data. The following method is called to send records that are created locally to CloudKit. I call this method when the app starts and when the app returns from the background. I also have programmed a button for the testing phase which calls this method.
The behavior seems to be completely random. For example if I create 10 records, some number of them are correctly uploaded to CloudKit and some number fail. If I rerun the method manually, eventually they all upload to CloudKit. I have been unable to determine ANY pattern for success or failure. At this point I seed test records from a method that makes the records all identical except for recordName(UUID) and a suffix for the text fields.
With limited testing if I create just one record it has always worked.
If I create just two records, an occasional failure.
If I create five records, there is almost always a failure.
Inside the modifyRecordsCompletionBlock, the updateSavedToCloudKitSuccess() and cleanUpTmpFile() always complete correctly regardless of whether the upload is successful.
I also tried increasing the timeouts and that makes absolutely no difference.
Any guidance would be appreciated. Xcode 8.3.3 iOS10 Swift 3
func saveNewCloudKitRecordFromCoreData( myRecordName : String ) {
//get the Core Data record
let patient = findPatientRecord(myRecordName: myRecordName)
privateDatabase = container().privateCloudDatabase
sharedDatabase = sharedContainer().sharedCloudDatabase
recordZone = CKRecordZone(zoneName: "myPatientZone")
let myRecordID : CKRecordID = CKRecordID(recordName: myRecordName, zoneID: (recordZone?.zoneID)!)
let myRecord = CKRecord(recordType: "Patient", recordID : myRecordID)
myRecord.setObject(myRecordName as CKRecordValue?, forKey: "myRecordName")
myRecord.setObject(patient.firstName as CKRecordValue?, forKey: "firstname")
//bunch more fields...
let modifyRecordsOperation = CKModifyRecordsOperation(recordsToSave: [myRecord], recordIDsToDelete: nil)
modifyRecordsOperation.timeoutIntervalForRequest = 10
modifyRecordsOperation.timeoutIntervalForResource = 10
modifyRecordsOperation.modifyRecordsCompletionBlock = {
records, recordIDs, error in
if let err = error {
print("error in modifyRecordsOperation \(err.localizedDescription)")
self.updateSavedToCloudKitSuccess(recordName: myRecordName, success: false)
self.cleanUpTmpFile()
} else {
print("success in modifyRecordsOperation")
self.currentRecord = myRecord
self.updateSavedToCloudKitSuccess(recordName: myRecordName, success: true)
self.cleanUpTmpFile()
}//if err
}//modifyRecordsOperation
privateDatabase?.add(modifyRecordsOperation)
}//saveNewCloudKitRecordFromCoreData
Console output example:
NOresults.count is: 7
success in modifyRecordsOperation
savedToCloudKit = true
error in modifyRecordsOperation Failed to modify some records
savedToCloudKit = false
error in modifyRecordsOperation Failed to modify some records
savedToCloudKit = false
error in modifyRecordsOperation Failed to modify some records
savedToCloudKit = false
error in modifyRecordsOperation Failed to modify some records
savedToCloudKit = false
success in modifyRecordsOperation
savedToCloudKit = true
success in modifyRecordsOperation
savedToCloudKit = true
Based on the comments from rmaddy and paulw11 I implemented the perRecordCompletionBlock and found that the errors always are related to the CKAsset file. I will look to see if I cleanup that temporary file before a completion block has executed.
perRecordCompletionBlock: "; dateCreated = "2017-08-21 22:20:25 +0000"; dateOfBirth = "2017-04-23 22:20:25 +0000"; firstname = FirstName12; lastname = ZLastName12; myRecordName = "7621A7BD-7D32-4984-8117-2189D6F40D5F"; notes = "This is note number12"; patientlistparent = ""; primaryPhysician = "Dr. Who12"; ssan = 123456789; }, recordType=Patient>. Error: Optional() error in modifyRecordsOperation Failed to modify some records savedToCloudKit = false