The function in question is the following.
func records(for ids: [CKRecord.ID], desiredKeys: [CKRecord.FieldKey]? = nil) async throws -> [CKRecord.ID : Result<CKRecord, Error>]
Note that the returned value looks like a dictionary of the form [CKRecord.ID : Result<CKRecord, Error>], but the input is an array of CKRecord.IDs.
There are similar functions, but they return a tuple. Like the below example.
func records(matching query: CKQuery, inZoneWith zoneID: CKRecordZone.ID? = nil, desiredKeys: [CKRecord.FieldKey]? = nil, resultsLimit: Int = CKQueryOperation.maximumResults) async throws -> (matchResults: [(CKRecord.ID, Result<CKRecord, Error>)], queryCursor: CKQueryOperation.Cursor?)
Note that matchedResults is an array of tuples consisting of [(CKRecord.ID, Result<CKRecord, Error>)].
I would have thought that the return type in the first function would also be of the form [(CKRecord.ID, Result<CKRecord, Error>)].
What am I missing?
The new signatures will give you a per-record result of Result<CKRecord, Error>
as described in the method signature. So when you ask for records with IDs "ABCD" and "EFGH", lets say only ABCD exists, you'll get a dictionary back with two key-value pairs, the first being ABCD with the result value of .success(CKRecord) and the second of EFGH and .failure(UnknownItem).
Have a watch of the session you linked (10086) from 2021 and take note of the changes to the CKFetchRecordsOperation. The same thinking to the per-record error reporting also makes its way into the convenience methods on CKDatabase.