0
votes

I need to do is to build two different apps, both under my developer account. Give one to the user to see the data in the database, and keep one handy to me to change this database. I am using CloudKit, default container and public database.

So what I have tried for now is I have one app for user let's say app name is "showdata". In that app I use the default container and public database like this:

let publicDatabase = CKContainer.default().publicCloudDatabase

And then I use this to perform query:

query = CKQuery(recordType: "updateAndHold", predicate: NSPredicate(format: "TRUEPREDICATE"))
publicDatabase.perform(query!, inZoneWith: nil) { (records, error) in

In the second app let's name it "updatedata". What I should do to use the same database and container to update the data. I have tried this code:

let container = CKContainer.init(identifier: "iCloud.com.WMWIOS.showdata").publicCloudDatabase

But when I fetch for any record it gives me error that no entitlement with that name:

query = CKQuery(recordType: "updateAndHold", predicate: NSPredicate(format: "TRUEPREDICATE"))
container.perform(query!, inZoneWith: nil) { (records, error) in

And when I print(publicDatabase) and print(container) it has different IDs but same identifier.

I need help with that issue. If you need any more info please let me know.

1

1 Answers

1
votes

This code checks for authorization using a named icloud database and includes extensive error checking.

func isAuthorized4Cloud() {
    appDelegate = UIApplication.shared.delegate as! AppDelegate
    container = CKContainer(identifier: "iCloud.blah.com")
    publicDB = container.publicCloudDatabase
    privateDB = container.privateCloudDatabase
    var userID: CKRecordID!
    container.fetchUserRecordID( completionHandler: { recordID, error in
        guard error == nil else {
            if let ckerror = error as? CKError {
                if ckerror.code == CKError.requestRateLimited {
                    let retryInterval = ckerror.userInfo[CKErrorRetryAfterKey] as? TimeInterval
                    DispatchQueue.main.async {
                        Timer.scheduledTimer(timeInterval: retryInterval!, target: self, selector: #selector(self.files_searchSet), userInfo: nil, repeats: false)
                    }
                } else if ckerror.code == CKError.zoneBusy {
                    let retryInterval = ckerror.userInfo[CKErrorRetryAfterKey] as? TimeInterval
                    DispatchQueue.main.async {
                        Timer.scheduledTimer(timeInterval: retryInterval!, target: self, selector: #selector(self.files_searchSet), userInfo: nil, repeats: false)
                    }
                } else if ckerror.code == CKError.limitExceeded {
                    let retryInterval = ckerror.userInfo[CKErrorRetryAfterKey] as? TimeInterval
                    DispatchQueue.main.async {
                        Timer.scheduledTimer(timeInterval: retryInterval!, target: self, selector: #selector(self.files_searchSet), userInfo: nil, repeats: false)
                    }
                } else if ckerror.code == CKError.notAuthenticated {
                    NotificationCenter.default.post(name: Notification.Name("noCloud"), object: nil, userInfo: nil)
                } else if ckerror.code == CKError.networkFailure {
                    NotificationCenter.default.post(name: Notification.Name("networkFailure"), object: nil, userInfo: nil)
                } else if ckerror.code == CKError.networkUnavailable {
                    NotificationCenter.default.post(name: Notification.Name("noWiFi"), object: nil, userInfo: nil)
                } else if ckerror.code == CKError.quotaExceeded {
                    NotificationCenter.default.post(name: Notification.Name("quotaExceeded"), object: nil, userInfo: nil)
                } else if ckerror.code == CKError.partialFailure {
                    NotificationCenter.default.post(name: Notification.Name("partialFailure"), object: nil, userInfo: nil)
                } else if (ckerror.code == CKError.internalError || ckerror.code == CKError.serviceUnavailable) {
                    NotificationCenter.default.post(name: Notification.Name("serviceUnavailable"), object: nil, userInfo: nil)
                }
            } // end of guard statement
            return
        }

        if error == nil {
            userID = recordID
            NotificationCenter.default.post(name: Notification.Name("cloudConnected"), object: nil, userInfo: nil)
        }
    })
}

You also might want to take a look at the permissions on the database itself in the cloudkit dashboard which will govern if an app can write into a given database or not.

enter image description here