问题描述
我对如何处理复杂的 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 和一个错误,它们在 (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
这很令人困惑..所以如果我理解正确,那么:
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,Error>>.Element
数据结构。 >
非常感谢您对理解的任何见解。
谢谢
更新
好的,根据@Shadowrun 的回答,如果我理解正确的话:
结果来自:
let result = try await container.privateCloudDatabase.records(matching: query)
是元组类型。这意味着它有两个元素,第一个是数据字典,第二个是查询光标。
如果我想遍历元组的 Dictionary 部分并取出 CKRecord:
for rec in result.0 {
self.myCKRecordArray.append(try rec.value.get())
}
这不会给我任何错误..我理解正确吗?
第二次更新 它确实以这种方式按预期工作。
解决方法
返回 .container-2 {
display: row; //alternatively just remove this,the default is row for flex direction
flex-direction: column;
}
的函数与返回 Result<T,E>
或抛出 T
的函数之间存在等价关系。以及返回 E
将带有完成处理程序的函数映射到异步函数时,它们变成了抛出函数
(T?,E?)
应该只是let (result,err) = try await container….
,如果有错误,则抛出
冒着迂腐的风险,我可以建议阅读文档吗?
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
。这样做的优点是它要么返回一个值,要么抛出,你可以很好地应对。