Search code examples
iosswifticloudcloudkit

iOS: CloudKit perform(query: ) does nothing - closure not executed


I am in process in adding CloudKit to my app to enable iCloud sync. But I ran into problem with my method, that executes query with perform method on private database.

My method worked fine, I then changed a few related methods (just with check if iCloud is available) and suddenly my perform method does nothing. By nothing I mean that nothing in perform(query: ) closure gets executed. I have breakpoint on the first line and others on the next lines but never manage to hit them.

private static func getAppDetailsFromCloud(completion: @escaping (_ appDetails: [CloudAppDetails]?) -> Void) {

        var cloudAppDetails = [CloudAppDetails]()
        let privateDatabase = CKContainer.default().privateCloudDatabase
        let query = CKQuery(recordType: APPID_Type, predicate: NSPredicate(format: "TRUEPREDICATE"))

        privateDatabase.perform(query, inZoneWith: nil) { (records, error) in
            if let error = error {
                print(error)
                completion(nil)
            } else {

                if let records = records {

                    for record in records {
                        let appId = record.object(forKey: APPID_ID_Property) as? Int
                        let isDeleted = record.object(forKey: APPID_ISDELETED_Property) as? Int

                        if let appId = appId, let isDeleted = isDeleted {
                            cloudAppDetails.append(CloudAppDetails(id: appId, isDeleted: isDeleted == 1))
                        }
                    }

                    completion(cloudAppDetails)
                    return

                }
            }
            completion(nil)
        }
    }

My problem starts at privateDatabase.perform line, after that no breakpoints are hit and my execution moves to function which called this one getAppDetailsFromCloud. There is no error...

This is my first time implementing CloudKit and I have no idea why nothing happens in the closure above.

Thanks for help.

EDIT: Forgot to mention that this metod used to work fine and I was able to get records from iCloud. I have not made any edits to it and now it does not work as described :/

EDIT 2: When I run the app without debugger attached then everything works flawlessly. I can sync all data between devices as expected. When I try to debug the code, then I once again get no records from iCloud.


Solution

  • In the completion handler shown here, if there's no error and no results are found, execution will fall through and quietly exit. So, there are two possible conditions happening here: the query isn't running or the query isn't finding any results. I'd perform the following investigative steps, in order:

    1. Check your .entitlements file for the key com.apple.dev.icloud-container-environment. If this key isn't present, then builds from xcode will utilize the development environment. If this key is set, then builds from xcode will access the environment pointed to by this key. (Users that installed this app from Testflight or the app store will always use the production environment).
    2. Open the cloudkit dashboard in the web browser and validate that the records you expect are indeed present in the environment indicated by step 1 and the container you expect. If the records aren't there, then you've found your problem.
    3. If the records appear as expected in the dashboard, then place the breakpoint on the .perform line. If the query is not being called when you expected, then you need to look earlier in the call stack... who was expected to call this function?
    4. If the .perform is being called as expected, then add an else to the if let record statement. Put a breakpoint in the else block. If that fires, then the query ran but found no records.
    5. If, after the above steps, you find that the completion handler absolutely isn't executed, this suggests a malformed query. Try running the query by hand using the cloudkit dashboard and observing the results.