I have an array of CKRecords that I'm trying to save to the default Container's public database for the first time. I created a CKModifyRecordsOperation and attempted to add the operation to the public database. It was unsuccessful but I'm not getting any error messages. So I tried adding each method individually to the database, sans any CKOperation... also unsuccessful, also devoid of error messages. To be sure, I checked my CloudKit Dashboard; there's nothing there.
Below is the method in question. It's hooked up to a simple IBAction for a button in an NSWindow. You can ignore the nested loops where I'm creating the CKRecords from my model data. They seem to be working as expected. My error checking code is inside of the completion blocks for CKModifyRecordsOperation. Specifically, the modifyRecordsCompletionBlock is printing: "Saved 0 records into CloudKit."
@IBAction func uploadDataToCloudKit(_ sender: NSButton) {
// Get CloudKit container and Public Database
let myContainer = CKContainer.default()
let publicDB = myContainer.publicCloudDatabase
// Create array of cloudkit records so we can save a batch
var cloudRecords = [CKRecord]()
let groups = PayCodes().groups
// For each PayCode Group...
for payCodeGroup in groups {
// Create CKRecord and give it a type
let payCodeGroupRecord = CKRecord(recordType: "payCodeData")
// For each PayCode in the group...
for payCode in payCodeGroup.payCodes {
// Fill the new CKRecord with key/value pairs
payCodeGroupRecord.setObject(payCodeGroup.title as NSString, forKey: "group")
if let commercialID = payCode.id.commercial as NSString?, let residentialID = payCode.id.residential as NSString? {
payCodeGroupRecord.setObject(commercialID, forKey: "commercialID")
payCodeGroupRecord.setObject(residentialID, forKey: "residentialID")
}
payCodeGroupRecord.setObject(payCode.title as NSString, forKey: "title")
if let description = payCode.description as NSString? {
payCodeGroupRecord.setObject(description, forKey: "description")
}
payCodeGroupRecord.setObject((payCode.includesTripCharge ? 1 : 0) as NSNumber, forKey: "includesTripCharge")
payCodeGroupRecord.setObject((payCode.needsResolutionCode ? 1 : 0) as NSNumber, forKey: "needsResolutionCode")
payCodeGroupRecord.setObject(payCode.pay.commercial as NSNumber, forKey: "commercialPay")
payCodeGroupRecord.setObject(payCode.pay.residential as NSNumber, forKey: "residentialPay")
// Save new CKRecord into the Array
cloudRecords.append(payCodeGroupRecord)
}
}
print("There are \(cloudRecords.count) records about to be saved...")
// print(cloudRecords)
// Create an operation to save the records
let operation = CKModifyRecordsOperation(recordsToSave: cloudRecords, recordIDsToDelete: nil)
operation.perRecordCompletionBlock = { savedRecord, error in
guard error != nil else {
print("There was an error: \(error!.localizedDescription)")
return
}
print("Saved a record into CloudKit")
}
operation.modifyRecordsCompletionBlock = { savedRecords, deletedRecordIDs, error in
guard error != nil else {
print("There was an error: \(error!.localizedDescription)")
return
}
guard let savedRecords = savedRecords else { return }
print("Saved \(savedRecords.count) records into CloudKit")
}
// Run the operation
publicDB.add(operation)
// cloudRecords.forEach { record in
// publicDB.save(record) { savedRecord, error in
// guard error != nil else {
// print("There was an error: \(error!.localizedDescription)")
// return
// }
//
// guard let savedRecord = savedRecord else { return }
// print("Saved a record: \(savedRecord.allKeys())")
// }
// }
}
Your problem with the duplicate records is your reuse of the CKRecord
instance.
Change:
for payCodeGroup in groups {
// Create CKRecord and give it a type
let payCodeGroupRecord = CKRecord(recordType: "payCodeData")
// For each PayCode in the group...
for payCode in payCodeGroup.payCodes {
// Fill the new CKRecord with key/value pairs
payCodeGroupRecord.setObject(payCodeGroup.title as NSString, forKey: "group")
to:
for payCodeGroup in groups {
// For each PayCode in the group...
for payCode in payCodeGroup.payCodes {
// Create CKRecord and give it a type
let payCodeGroupRecord = CKRecord(recordType: "payCodeData")
// Fill the new CKRecord with key/value pairs
payCodeGroupRecord.setObject(payCodeGroup.title as NSString, forKey: "group")