Pierce
Pierce

Reputation: 3158

Save Multiple CKRecords At One Time Using CloudKit and Swift

Is it possible to save multiple CKRecord objects in one CloudKit operation using Swift? I know how to retrieve multiple records at once, using things like CKFetchRecordsOperation or even just a regular performQuery. I just realized that I am not sure of a way to save multiple new records in one operation. The way I have been doing that so far, seems inefficient to me. For example:

let recordsToSave:[CKRecord]!

for newRecord in recordsToSave {

    if let database = self.publicDatabase {

        database.saveRecord(newRecord, completionHandler: { (record:CKRecord?, error:NSError?) in

            // Check if there was an error
            if error != nil {

                // There was an error, handle it properly.

            }
            else {

                // There wasn't an error
                if let savedRecord = record {

                    // Handle saved record accordingly.

                }

            }
        })
}

And while that does work all fine and dandy, it seems to me as though it's extremely inefficient. I would think it would make more sense to have a specific function to call to save the entire array of CKRecords, instead of having to make a database call every time through the loop. Essentially here is what I'm hoping I can do:

let recordsToSave:[CKRecord]!

if let database = self.publicDatabase {

    // SOMETHING HERE LIKE database.saveRECORDS (plural) ????
    database.saveRecords(recordsToSave, completionHandler: { (records:[CKRecord]?, error:NSError?) in

        // Check if there was an error
        if error != nil {

            // There was an error, handle it properly.

        }
        else {

                // There wasn't an error
                if let savedRecords = records {


                }

            }
        })
}

As best as I can tell, and based on the information I've obtained. There isn't an actual function like database.saveRecords (plural). Unless I am missing something? I'm thinking that its not so cut and dry and that the naming is different, but I would assume there has to be something similar to that.

It seems so horribly inefficient to have to make a database call every time I go through the loop.

Does anybody know of a method to execute a save for multiple CKRecords at one time, using CloudKit? Any help at all would be greatly appreciated. Thank you in advance!

Upvotes: 10

Views: 3242

Answers (2)

Alex Aghajanov
Alex Aghajanov

Reputation: 326

To build on what rmaddy said, here is an example code, which also works for deleting if you add an array of CKRecords in the "delete" parameter (which I have as nil here). Here's what I mean:

let db = CKContainer.default().publicCloudDatabase
            
let operation = CKModifyRecordsOperation.init(recordsToSave: recordsToSave, recordIDsToDelete: nil)
operation.modifyRecordsCompletionBlock = { _, _, error in
    if let error = error{
        print(error.localizedDescription)
        let alert = UIAlertController(title: "Operation Failed", message: "There was a problem interacting with some records.", preferredStyle: .alert)
        let ok  = UIAlertAction(title: "Ok", style: .cancel, handler: nil)
        alert.addAction(ok)
        self.present(alert, animated: true, completion: nil)
    }
}
db.add(operation)

Upvotes: 5

rmaddy
rmaddy

Reputation: 318774

Using saveRecord in a loop is terribly inefficient. It's actually best to avoid all of the convenience methods on CKDatabase and use the appropriate operation.

To add/modify/delete one or more records, use CKModifyRecordsOperation. You can add/modify as well as deleted any number of records with a single operation. This will be vastly more efficient than using saveRecord.

I suggest you browse through the CloudKit Framework Reference to see the complete list of operations available.

Upvotes: 16

Related Questions