What is the proper way to read shared items from the Shared Database in CloudKit

I have an app where I can create and share records with other users. When I share a record and the user accepts it, I can display the shared object right after the `userDidAcceptCloudKitShareWith` gets called and using the `CKFetchRecordsOperation` class to fetch the object, no issues here. My problem is trying to read the shared records directly from the `Shared Database` after the user has accepted the record, closed the app, and reopened the app again.



The following code successfully reads all of the records from the `Private Database` located in a zone called `ListsZone`.



    @IBAction func sharedRecords(_ sender: Any) {
        let privateDatabase = CKContainer.init(identifier: "iCloud.com.mySite.lists").database(with: .private)


        let predicate = NSPredicate(value: true)
        let query = CKQuery(recordType: "Items", predicate: predicate)
       
        let ckRecordZoneID = CKRecordZone(zoneName: "ListsZone")
        let ckRecordID = CKRecord.ID(zoneID: ckRecordZoneID.zoneID)


        privateDatabase.perform(query, inZoneWith:ckRecordID.zoneID){( results , error) in
            guard error == nil else{
                print("Error \(String(describing: error?.localizedDescription))")
                return
            }
            if let itemsFromResults = results{
                print("Items: \(itemsFromResults)")
            }
        }
    }


What I'm expecting is to be able to read the shared records from the `Shared Database` with the same code above except modifying the line below, but it's not working.



let privateDatabase = CKContainer.init(identifier: "iCloud.com.mySite.lists").database(with: .shared)


I get the following error.


"Only shared zones can be accessed in the shared DB"


What am I missing?


What is the proper way to read records from the `Shared Database`?


I was under the impression that users who already accepted a shared record from a user and the records are saved in the `Shared Database` the user could access the records by requiring the `Shared Database` directly as shown in my code above.


FYI - I know there are shared records in the shared database because I can see them in the CloudKit dashboard.

Answered by fsdolphin in 419307022

Apparently the name of your `CustomZone` record changes when it gets added to the Shared Database so, you first need to retrieve all custom zones from the shared database.


I found the answer thanks to the following two threads.


https://stackoverflow.com/questions/40603657/cloudkit-sharing


https://stackoverflow.com/questions/56163096/unable-to-fetch-records-in-a-sharedclouddatabase-custom-zone-using-cloudkit


##CODE:


    @IBAction func readSharedRecords(_ sender: Any) {
       
        let sharedData = CKContainer.default().sharedCloudDatabase
        sharedData.fetchAllRecordZones { (recordZone, error) in
            if error != nil {
                print(error?.localizedDescription ?? "Error")
            }
            if let recordZones = recordZone {
                for i in 0..<recordzones.count{
                    // find the zone you want to query
                    if recordZones[i].zoneID.zoneName == "ListsZone"{
                        self.sharedRecords(zID: recordZones[i].zoneID)
                    }
                }
            }
        }
    }


    func sharedRecords(zID: CKRecordZone.ID){
        let privateDatabase = CKContainer.init(identifier: "iCloud.com.mySite.lists").database(with: .shared)


        let predicate = NSPredicate(value: true)
        let query = CKQuery(recordType: "Items", predicate: predicate)


        privateDatabase.perform(query, inZoneWith: zID){( results , error) in
            guard error == nil else{
                print("Error: \(String(describing: error?.localizedDescription))")
                return
            }
            if let itemsFromResults = results{
                print("Items: \(itemsFromResults)")
            }
        }
    }
Accepted Answer

Apparently the name of your `CustomZone` record changes when it gets added to the Shared Database so, you first need to retrieve all custom zones from the shared database.


I found the answer thanks to the following two threads.


https://stackoverflow.com/questions/40603657/cloudkit-sharing


https://stackoverflow.com/questions/56163096/unable-to-fetch-records-in-a-sharedclouddatabase-custom-zone-using-cloudkit


##CODE:


    @IBAction func readSharedRecords(_ sender: Any) {
       
        let sharedData = CKContainer.default().sharedCloudDatabase
        sharedData.fetchAllRecordZones { (recordZone, error) in
            if error != nil {
                print(error?.localizedDescription ?? "Error")
            }
            if let recordZones = recordZone {
                for i in 0..<recordzones.count{
                    // find the zone you want to query
                    if recordZones[i].zoneID.zoneName == "ListsZone"{
                        self.sharedRecords(zID: recordZones[i].zoneID)
                    }
                }
            }
        }
    }


    func sharedRecords(zID: CKRecordZone.ID){
        let privateDatabase = CKContainer.init(identifier: "iCloud.com.mySite.lists").database(with: .shared)


        let predicate = NSPredicate(value: true)
        let query = CKQuery(recordType: "Items", predicate: predicate)


        privateDatabase.perform(query, inZoneWith: zID){( results , error) in
            guard error == nil else{
                print("Error: \(String(describing: error?.localizedDescription))")
                return
            }
            if let itemsFromResults = results{
                print("Items: \(itemsFromResults)")
            }
        }
    }

When you create the zone it adds the owner name as a suffix, so you need to retrieve that from the record or like said above, by querying the zones again.