How to know if the CloudKit Zone exists already
Asked Answered
M

2

7

To add a CKRecord in a private CKRecordZone you need to make sure the zone exists already.

But does it mean that every time I need to insert a record I need to fetch all the zones and find if my zone exists using fetchAllRecordZonesWithCompletionHandler ? It wouldn't be very efficient.

What is the best strategy to adopt ?

Most of the examples I have seen show how to create a zone and add a record into it. But you are not going to create the zone every time, and you can't just assume it exists...

Code below will fail if the zone has not been created already

let customZone = CKRecordZone(zoneName: self.zoneName!)
// Create a CKRecord
let lessonRecord = CKRecord(recordType: self.recordType, zoneID: customZone.zoneID)

Thanks for your help.

Meit answered 26/5, 2016 at 4:38 Comment(0)
A
10

To see if a specific zone exists, use CKFetchRecordZonesOperation and pass just the one record zone ID.

You only need to do this once if your code is setup properly.

Create a class that represents a record zone. This class should perform all of the CloudKit operations for a given zone. When you initialize an instance of this class for a specific zone, you can check to see if the zone exists. If not, then create the zone. Then you use that specific instance of this zone helper class each time you need to read or write data to that zone.

Of course every read and write operation needs to check error results to check for CKErrorZoneNotFound errors. Getting such an error probably means the zone was deleted from another copy of the app.

Aminoplast answered 26/5, 2016 at 14:15 Comment(4)
It's weird, to me. Why can't we just create zones from the dashboard? Does this also mean that we could create a zone from a dev version of our app, then delete that code and never use create zone code again in release builds, just assuming that the zone exists? (Not using any way of deleting zones from the app either)Maxi
Zones exist only the private database. You can't pre-fill zones or records in someone's private database. They have to be created for each user that uses your app.Meit
@Maxi It would not do any good to create a zone in the dev version. 1) The zone would only exist in your own private database in development. 2) The zone would not exist in the production private database.Aminoplast
Ah ok sorry of course yes that makes sense. Well to be correct zones exist in the shared database too.Maxi
N
0

Another way to avoid checking if a zone exists or not is to handle the error message when trying upload a record to a zone that does not exist. Since most records will succeed in the upload, this would seem more efficient.

database.save(record) { record, error in
    if record != nil, error == nil {
        print("** Saved new record in iCloud")
    } else {
        if let error = error as? CKError, error.code == .zoneNotFound {
            self.createNewZone(zone: cZone)
        }
    }
}
Nebulosity answered 27/7, 2023 at 19:27 Comment(2)
Checking the error's localized description is a terrible solution. The correct solution is to check the error's code. if let error = error as? CKError, error.code == .zoneNotFound {. And don't forget to re-save the failed record after creating its zone.Fadden
I agree. I tried looking for the .code first, but was getting an error (Value of type 'any Error' has no member 'code'). I was missing the as? CKError. Thanks for the correction.Nebulosity

© 2022 - 2024 — McMap. All rights reserved.