2

I am having issues deleting CloudKit records. This is my first time dealing with the API and apparently there are two ways to do this.

Saving records is straight forward and ostensibly so is deleting them, except this doesn't do it:

func deleteRecords() {

    let recordID = record.recordID
    publicDatabase.delete(withRecordID: recordID) { (recordID, error) in
        guard let recordID = recordID else {
        print(error!.localizedDescription)
            return
    }
        print("Record \(recordID) was successfully deleted")
    }
}

I understand using a ckModifyRecordsOperation is another way to do this but this is a batch operation. I only need to delete one record at a time. Here's my code for that:

 func batchDelete() {
    let recordIDsToDelete = [CKRecordID]()
    let operation = CKModifyRecordsOperation(recordsToSave: nil, recordIDsToDelete: recordIDsToDelete)
    operation.modifyRecordsCompletionBlock = { savedRecords, deletedRecordIDs, error in
        // handle errors here
    }
    publicDatabase.add(operation)
    print("Batch \(recordIDsToDelete) record was successfully deleted")
}

Neither of these separately or together are working for me.

  • Nobody but you knows what 'publicDatabase' is. – El Tomato Dec 07 '17 at 14:04
  • `public let publicDatabase = CKContainer.default().publicCloudDatabase` – davidoliverdoswell Dec 07 '17 at 14:09
  • You've provided no useful details. What actually happens when you run this code? In your `deleteRecords` method, what happens in the completion handler? And note that in your `batchDelete` method you don't attempt to delete anything since you are passing an empty array. – rmaddy Dec 07 '17 at 20:52
  • I'll give you a down vote for repeatedly leaving out crucial pieces of information. – El Tomato Dec 08 '17 at 00:47
  • @maddy nothing. I can delete the row in the tableView and refresh. My `refreshTable` queries the database again and reloads the table, but the row I deleted appears again. Why would the record not be deleted from the database is what I am asking. – davidoliverdoswell Dec 08 '17 at 02:35
  • @ElTomato if you've used `cloudKit` before you would recognize the code. There is no other way to instantiate it. It's a simple question of why [this](https://developer.apple.com/documentation/cloudkit/ckmodifyrecordsoperation/1447479-recordidstodelete) and [this](https://developer.apple.com/documentation/cloudkit/ckdatabase/1449122-delete) differ when they both are supposed to be deleting `recordIDs`, which I instantiate with (again, if you've used `cloudKit` : `let record = CKRecord(recordType: "RecordName")` – davidoliverdoswell Dec 08 '17 at 02:36
  • It's a simple question of why you don't provide every single detail about your project. What is the name of the record type? How are security roles set? What is the cloud database name? Why are you using the public cloud database as oppsed to the priviate cloud database? – El Tomato Dec 08 '17 at 02:47
  • 1. See previous post about `recordType`. Not necessary to know for using the methods I provided. 2. Security roles? For deletions? 3. The name of my project, Again, nothing to do with deletions. 4. Because the `publicDatabase` is where everyone's data in the project is stored. There are no profiles. Again, nothing to do with deleting records. – davidoliverdoswell Dec 08 '17 at 02:59
  • @ElTomato Apologies for an insufficient question and response. I have been frustrated with a certain project and took it out on you all. I'm sorry. I will ask the question again tomorrow with a thorough workup of what I am trying to accomplish. – davidoliverdoswell Dec 08 '17 at 03:49

1 Answers1

2

You are correct, there are two ways. The first way you describe is referred to by Apple as a "convenience" function. If you're just deleting a single record, it's probably the quickest option to implement. However, each convenience operation conducts its own trip to the database. If you loop through thousands of records and delete them individually with the convenience function, you're going to use a lot of your cloudKit quota making a series of individual calls.

The second option, the operation, let's you batch the deletes and send them in one operation. Generally, this will be a more efficient use of your cloudkit quotas. But, according to Apple docs, there's no technical difference between the two; the the convenience function is just a wrapper to the operation.

Now, to your specific problem, the operation has two separate completion blocks: perRecordCompletionBlock and modifyRecordsCompletionBlock. As the names imply, the first block is called after each and every record is processed in the operation and that's where errors are surfaced. Make sure you implement perRecordCompletionBlock and check for errors there (and then you'll have to decide if your error handling steps belong in the perRecordCompletionBlock or the modifyRecordsCompletionBlock).

Finally, if the operation (or convenience function) is running and you confirm that the completion blocks fire without errors but the record still doesn't delete, this typically indicates you passed nil rather than a valid record to the deletion.

Thunk
  • 4,099
  • 7
  • 28
  • 47
  • Thank you! I will implement this and see what happens. I read this in the docs and couldn't get errors because (I think) I didn't implement `perRecordCompletionBlock` :) – davidoliverdoswell Dec 09 '17 at 04:31