Понимание результата выборки CKRecords с новым API async/await

Я немного запутался в том, как работать со сложными типами данных Swift, их назначением переменным и доступом к внутренним значениям. Надеюсь, кто-то сможет прояснить следующее:

при попытке получить данные из SwiftUI и CloudKit и при попытке переписать функцию CK в соответствии с async / await у меня есть следующая строка кода:

let result = try await container.privateCloudDatabase.records(matching: query)

теперь эта строка должна получить все записи, соответствующие указанному запросу, из частной облачной базы данных и вернуть некоторые записи CKRecords

Старая функция делала это следующим образом:

      container.privateCloudDatabase.perform(query, inZoneWith: nil) { (rec, err) in 
    for record in rec {
        print("Found this record: \(record)")
    }
}

и это отлично сработало, потому что perform(_:inZoneWith:) вернет CKRecord и Error, которые были "разобраны" в (rec, err) in оператор и передается в цикл для повторения.

С новым методом async / await я пытаюсь просто ждать и назначать переменную всем найденным записям, а затем перебирать возвращаемые данные, выбирать CKRecords и выполнять любую задачу, которую я хочу.

Что меня смущает, так это то, что когда я пытаюсь разными способами выбрать данные из возвращенного результата, я просто получаю ошибки. Я не совсем понимаю, как описывать структуру данных возвращаемых значений, и я думаю, что это основная причина проблемы.

Я пробовал несколько вещей и получил следующие сообщения об ошибках:

если я попробую:

      let (result, err)  = try await container.privateCloudDatabase.records(matching: query)

Когда я использую (пытаюсь добавить CKRecords в массив CKRecords, который я создал ранее):

      for record in result {
   self.myCKRecordArray.append(record)
}

в сообщении об ошибке конкретно указано:

Cannot convert value of type 'Dictionary<CKRecord.ID, Result<CKRecord, Error>>.Element' (aka '(key: CKRecord.ID, value: Result<CKRecord, Error>)') to expected argument type 'CKRecord'

Что определенно дает мне некоторые подсказки. Я считаю что мой result переменная содержит элемент Dictionary<CKRecord.ID, Result<CKRecord, Error>>. или список пар ключ / значение, в котором CKRecord.ID является ключом для значения Result<CKRecord, Error>.

Это довольно сбивает с толку .. Итак, если я правильно понимаю, то:

              for thisDict in result {
            let (realResult, err) = result[thisDict.key]
            print("Found this record: \(realResult)")
        }

теоретически должен приводить к выводу каждой записи CKRecord, назначенной realResult, верно? Я просто получаю сообщение об ошибке: Type of expression is ambiguous without more context

Я пытался изменить это на valueForKey а также дать ему больше контекста, но без изменений по сравнению с сообщением об ошибке:

      let (realResult, err) = result(valueForKey:thisDict.key) as Result<CKRecord, Error>

Я просто считаю, что не совсем понимаю, как правильно получить доступ к CKRecord из чего-то, что представлено: Dictionary<CKRecord.ID, Result<CKRecord, Error>>.Element структура данных.

Мы очень ценим любое понимание.

Спасибо

Обновлять

Хорошо, на основе ответа от @Shadowrun, если я правильно понимаю:

Результат от:

      let result  = try await container.privateCloudDatabase.records(matching: query)

является кортежным типом. Это означает, что он состоит из двух элементов: первый - это словарь данных, а второй - это queryCursor.

Если я хочу перебрать часть словаря кортежа и получить CKRecord:

              for rec in result.0 {
            self.myCKRecordArray.append(try rec.value.get())
        }

Это не дает мне никаких ошибок .. Правильно ли я это понимаю?

2-е обновление работает так, как ожидалось.

2 ответа

Существует эквивалентность между функциями, возвращающими Result<T, E> и функции, которые либо возвращают T или бросить E. И аналогичная эквивалентность для функций, возвращающих кортеж из (T?, E?)

При отображении функций с обработчиками завершения на асинхронные функции они становятся функциями бросания

      let (result, err)  = try await container….

Должно быть просто let result = ..., выдается ошибка, если таковая имеется

Рискуя проявить педантичность, могу я предложить прочитать документацию?

https://developer.apple.com/documentation/cloudkit/ckdatabase/3794332-records

      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?)

Итак, ваш результат - кортеж. Назовите свой результат tuple. потом tuple.matchResults - словарь с ключом ID, значения которого являются объектами Result.

На мой взгляд, лучший способ извлечь значение из объекта Result - использовать get. Это имеет то преимущество, что он либо возвращает значение, либо выбрасывает, и вы можете хорошо с этим справиться.

Другие вопросы по тегам