swiftdeprecatedcloudkitckrecordckquery

How to do CloudKit Query Operations in iOS 16+?


CKQueryOperation recordFetchBlock and queryCompletionBlock have been deprecated. How would I complete this operation now?

queryOperation.recordFetchedBlock = { record in
    if let location = record["location1"] as? CLLocation {
        var hideEvent: Bool = false
        if let takeaway = record["host"] as? String {
            for blockee in self.blockedFeed {
                if takeaway == blockee {
                    hideEvent = true
                }
            }
            for blocker in self.blockedFeeder {
                if takeaway == blocker {
                    hideEvent = true
                }
            }
            if hideEvent == false {
                let identified = record.recordID.recordName
                let category = record["type"] as? String ?? "defaultCategory"

                let feature = """
            {
                "type": "Feature",
                "properties": {
                    "category": "\(category)",
                    "recordID": "\(identified)"
            },
                "geometry": {
                    "type": "Point",
                    "coordinates": [\("\(location.coordinate.longitude)"), \("\(location.coordinate.latitude)")]
                }
            }
            """
                features.append(feature)
            }
        }
    }
}

// Completion block
queryOperation.queryCompletionBlock = { cursor, error in
    if let error = error {
        print("Error:", error)
        return
    }
    if let cursor = cursor {
        // Create a new operation with the cursor to get the next batch
        let newOperation = CKQueryOperation(cursor: cursor)
        newOperation.resultsLimit = CKQueryOperation.maximumResults
        newOperation.recordFetchedBlock = queryOperation.recordFetchedBlock
        newOperation.queryCompletionBlock = queryOperation.queryCompletionBlock
        publicDB.add(newOperation)
    } else {
        let geoJSONString = """
        {
            "type": "FeatureCollection",
            "features": [\(features.joined(separator: ","))]
        }
        """
        completion(geoJSONString.data(using: .utf8))
    }
}

publicDB.add(queryOperation)

Solution

  • If you use code completion in Xcode, it shows you the replacement for recordFetchedBlock. The replacement is recordMatchedBlock.

    Xcode code completion also shows the replacement for queryCompletionBlock (which was deprecated in iOS 15 apparently). The replacement is queryResultBlock.

    enter image description here


    The basic pattern for the two completion blocks is now:

    let q = CKQueryOperation()
    // other setup as needed
    
    q.recordMatchedBlock = { recordID, result in
        switch result {
            case .success(let record):
                // Handle success
                print("RecordID: \(recordID), record: \(record)")
            case .failure(let error):
                // Handle error
                print("Failed for \(recordID): \(error)")
        }
    }
    
    q.queryResultBlock = { result in
        switch result {
            case .success(let cursor):
                // Handle success and use cursor as needed
                print("success")
            case .failure(let error):
                // Handle error
                print(error)
        }
    }