Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

ckqueryoperation in CloudKit crashing

Use CloudKit's ckqueryoperation's recordmatchedblock in Swift 6.0, which always crashes, but works fine in Swift 5: func fetchAllRecords() async throws { let predicate = NSPredicate(format: "Topics = %@", "Integrations") let query = CKQuery(recordType: "PureMList", predicate: predicate)

    let operation = CKQueryOperation(query: query)

    operation.recordMatchedBlock = { recordID, result in
        switch result {
        case .success(let record):
            DispatchQueue.main.async {
                        // Ensure UI updates happen here
                        print("Fetched record: \(record)")
                        // Update your UI elements here
                    }
        case .failure(let error):
            // Handle the error
            print("Error fetching record with ID \(recordID): \(error)")
        }
    }


    // Ensure you're using the correct database

    publicDatabase.add(operation)
}
Answered by DTS Engineer in 811042022

If it is a crash that occurs at _dispatch_assert_queue_fail in libdispatch.dylic when you adopt Swift 6, please see here for an in-depth analysis.

Basically, Swift 6 inserted a runtime check to detect concurrency issues, and if indeed detecting an issue, it (intentionally) triggers a crash. The Swift compiler doesn't spot the issue at compile time because of "a Swift / Objective-C impedance mismatch."

To solve the issue, I'd consider two options:

  1. Use async APIs. Concretely in your case, you can replace CKQueryOperation with records(matching:inZoneWith:desiredKeys:resultsLimit:) and records(continuingMatchFrom:desiredKeys:resultsLimit:).

  2. Make the closure passed to CKQueryOperation sendable:

operation.recordMatchedBlock = { @Sendable (recordID, result) in
   ...
}

You can give it a try and follow up here if this doesn't help.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Accepted Answer

If it is a crash that occurs at _dispatch_assert_queue_fail in libdispatch.dylic when you adopt Swift 6, please see here for an in-depth analysis.

Basically, Swift 6 inserted a runtime check to detect concurrency issues, and if indeed detecting an issue, it (intentionally) triggers a crash. The Swift compiler doesn't spot the issue at compile time because of "a Swift / Objective-C impedance mismatch."

To solve the issue, I'd consider two options:

  1. Use async APIs. Concretely in your case, you can replace CKQueryOperation with records(matching:inZoneWith:desiredKeys:resultsLimit:) and records(continuingMatchFrom:desiredKeys:resultsLimit:).

  2. Make the closure passed to CKQueryOperation sendable:

operation.recordMatchedBlock = { @Sendable (recordID, result) in
   ...
}

You can give it a try and follow up here if this doesn't help.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Works, thanks

ckqueryoperation in CloudKit crashing
 
 
Q