【发布时间】:2020-02-12 19:14:35
【问题描述】:
我按照 firebase 网站上的指示,想出了下面标记为 NEW CODE 的代码。我得到的错误是:
无法使用类型为“(@escaping () throws -> CombinedModel?)”的参数列表调用类型“Result”的初始化程序
我曾尝试研究 Result 对象和此错误,但没有找到任何可以直接帮助我的东西。我能够使用旧方式(我将在下面发布)读取数据,但我正在尝试遵循 Google 的文档 (https://firebase.google.com/docs/firestore/query-data/get-data)
任何帮助将不胜感激,谢谢!
旧代码
func readData(word: String) -> CombinedModel? {
print("reading data")
let docRef = db.collection(K.FBConstants.dictionaryCollectionName).document(word)
var wordResults: CombinedModel? = nil
docRef.getDocument { (document, error) in
if let e = error {
print("Error loading data: \(e)")
return
} else {
do {
if let resultData = try document?.data(as: CombinedModel.self){
print("Definitions: \(resultData.definitionsArray)")
print("\n Synonyms: \(resultData.synonyms)")
wordResults = resultData
}
} catch {
print("Error decoding: \(error)")
}
}
}
return wordResults
}
新代码
func newReadData(word: String) -> CombinedModel? {
let docRef = db.collection(K.FBConstants.dictionaryCollectionName).document(word)
docRef.getDocument { (document, error) in
let result = Result {
try document.flatMap {
try $0.data(as: CombinedModel.self)
}
}
switch result {
case .success(let combinedModel):
if let combinedModel = combinedModel {
print("CombinedModel: \(combinedModel)")
} else {
print("Document does not exist")
}
case .failure(let error):
print("Error decoding city: \(error)")
}
}
}
这是我为读取数据而创建的可编码自定义类。
struct CombinedModel: Codable {
var definitionsArray: [WordModel]
var synonyms: [String]
private enum CodingKeys: String, CodingKey {
case definitionsArray
case synonyms
}
}
struct WordModel: Codable {
let id: String
let partOfSpeech: String
let definitions: [String]
let example: [String]
let ipa: String
let audio: String
private enum CodingKeys: String, CodingKey {
case id
case partOfSpeech
case definitions
case example
case ipa
case audio
}
}
struct ThesaurusModel: Codable {
var synonyms: [String]
private enum CodingKeys: String, CodingKey {
case synonyms
}
}
【问题讨论】:
-
你为什么要这样做
let result = Result?在这个用例中它没有任何用途。为什么这个-> CombinedModel?作为你的函数不(也不应该)返回任何东西。你能澄清你在这里尝试什么吗?可能有一些方法可以显着简化该代码。 -
我同意有一些方法可以简化代码。我只是想遵循谷歌关于他们如何推荐阅读自定义对象的文档。如果您点击此链接,您可以看到我在说什么。这对我来说更重要的是试图了解这样做的方法并更好地掌握 swift 5 拥有的新 Result 对象。 firebase.google.com/docs/firestore/query-data/get-data
-
明白。澄清一下,Firestore 没有自定义对象,因此代码不会读取自定义对象。它正在读取文档(DocumentSnapshot)并将文档字段转换为 your 对象(文档中的 City 对象)。另请注意,文档中的代码不会返回任何内容(因为它不能)。只是想为您节省一些悲伤!
-
谢谢你的澄清,我边走边学,所以有时我无法理解代码,这真的很有帮助。我最终在闭包之外创建了一个变量,将其设置在闭包中,然后将其返回。我认为它工作正常(如果我错了,请纠正我)但是现在当我在其他函数中调用 read 函数时,似乎代码执行不正常。我想我需要一个我现在正在阅读的完成处理程序,但是如果您有任何建议,我很想听听!
-
Firebase 是异步的,因此让 Firebase 闭包控制其余代码的节奏。 #1 事情是不要尝试从闭包返回数据 - 在闭包之外设置类级别的 var 很好,但请确保在闭包完成之前不要做任何该 var 的事情。正如您所提到的,您可以利用完成处理程序。但是,假设您正在填充 tableView 数据源;从 Firebase 读取数据,对其进行迭代以填充数组,然后仍在闭包内,在 for 循环之后,调用 tableView.reloadData。如果您遇到困难,请发布另一个问题!
标签: swift firebase google-cloud-firestore codable decodable