After two hours of trying to figure out why the compiler says "Type of expression is ambiguous without more context" I could use another pair of eyes on this. What am I missing?
Swift 5.7 seems to have regressed the ability of the compiler to actually detect errors, especially in closures. Often this message means there's another error somewhere in the closure, so a good approach is comment out the content and reenable it a line at a time. It should succeed and then start failing at some point so you can narrow down your error. In this case, one possibility is the use of Cont
in the closure type, as that's not the type of the continuation, which you really shouldn't need in the first place.
Cosign. Usually when I hit this, I just copy and paste every part into a separate func, and then suddenly the compiler tells me actually what I did wrong. Then I fix and assemble everything back together :P
Thanks for the tips! I found a way around this that doesn't require the use of withCheckedThrowingContinuation. Here is my new code for retrieving records from CloudKit and utilizing cursors. This is based on ideas from Sean Allen's Dub Dub Grub course:
func retrieve<T: CloudKitable>(
recordType: CKRecord.RecordType,
predicate: NSPredicate = NSPredicate(value: true), // gets all
sortDescriptors: [NSSortDescriptor]? = nil,
resultsLimit: Int = CKQueryOperation.maximumResults
) async throws -> [T] {
let query = CKQuery(recordType: recordType, predicate: predicate)
query.sortDescriptors = sortDescriptors
let (results, cursor) = try await database.records(
matching: query,
resultsLimit: resultsLimit
)
// Get array of records, removing nils from failed calls to "get".
let records = results.compactMap { _, result in try? result.get() }
var objects = records.map { record in T(record: record)! }
try await retrieveMore(cursor, &objects)
return objects
}
private func retrieveMore<T: CloudKitable>(
_ cursor: Cursor?, _ objects: inout [T]
) async throws {
guard let cursor = cursor else { return }
let (results, newCursor) =
try await database.records(continuingMatchFrom: cursor)
// Get array of records, removing nils from failed calls to "get".
let records = results.compactMap { _, result in try? result.get() }
let newObjects = records.map { record in T(record: record)! }
objects.append(contentsOf: newObjects)
// Recursive call.
try await retrieveMore(newCursor, &objects)
}
Thanks mate, great strategy, didn't realise it was the code within my closure, really helped!!
I'm really late to the party, but since I encountered the same issue and I managed to solve it without abandoning the CKQueryOperation solution, I want to give my contribute for the next readers.
The issue is in what is returned by the queryResultBlock
.
If you carefully look at its sign, it says that it returns a Result<CKQueryOperation.Cursor?, any Error>
and... nothing else.
So, by writing:
operation.queryResultBlock = { result in
// your code...
}
and not:
operation.queryResultBlock = { result, error in
// your code...
}
you resolve the compiling error.
Just a little reading error :)