【问题标题】:Why can I not modify a variable declared outside a closure?为什么我不能修改在闭包外声明的变量?
【发布时间】:2020-09-04 17:21:47
【问题描述】:

每次我测试我的代码时,pickerUI 都会返回一个空字符串,而不是学院名称。这是为什么?调试时,docData 设置正确,但在关闭后变回空字符串。

var ans = "";
var pickerData = [Any?]();
let db = Firestore.firestore();

override func viewDidLoad() {
    super.viewDidLoad();
    let docRef = db.collection("colleges").document("UMD");
    var docData = "";
    docRef.getDocument {  ( document, error) in
        if error == nil {
            docData = document!.get("Name") as! String;

        } else{

        }
    }
    pickerData.append(docData);
    picker.delegate = self
    picker.dataSource = self
}

【问题讨论】:

标签: swift firebase google-cloud-firestore closures swift4


【解决方案1】:

这是因为数据是从 Firestore 异步加载的,而您的主代码会在此期间继续运行。通过放置一些日志语句最容易看到:

let docRef = db.collection("colleges").document("UMD")
print("Before starting to get data")
docRef.getDocument {  ( document, error) in
    print("Got data")
}
print("After starting to get data")

当你运行这段代码时,它会打印:

开始获取数据之前

开始获取数据后

得到数据

这可能不是您期望的顺序,但它确实完全解释了为什么您的代码不起作用。当你的pickerData.append(docData) 运行时,docData = document!.get("Name") as! String 还没有运行。

因此,任何需要数据库数据的代码都需要在闭包内,或者从那里调用:

let docRef = db.collection("colleges").document("UMD")
var docData = ""
docRef.getDocument {  ( document, error) in
    if error == nil {
        docData = document!.get("Name") as? String ?? "No Name"

        pickerData.append(docData)
        picker.delegate = self
        picker.dataSource = self
    } else{

    }
}

另见:

【讨论】:

  • 投反对票的人:你能解释一下你投反对票的原因吗?
  • 很好的答案!不知道为什么它被否决了。你不需要 ;在每一行之后。同样安全地打开选项可能是一个好主意guard let doc = document else { return } 然后let docData = doc.get("Name") as? String ?? "No Name"
  • 嘿,杰。关于分号的好点,我删除了它们。我要离开硬铸,因为保证闭包要么得到错误文档。只有在不满足该保证的情况下,硬演员才会失败,这……嗯……不是保证的意义所在。 :)
  • 同意!我想知道为什么docs 将 FIRDocumentSnapshotBlock 的两个参数都显示为可选 - 我猜如果存在 is 错误,那么快照可能为零? Anyhoo.. 这部分虽然.get("Name") 需要它,就好像文档没有名称字段一样,它会崩溃。
  • 哦,我不太喜欢这个API签名。 Flutter 为这种类型的异步数据提供了一个包装器对象,因此 never 为 null。但我更喜欢两个回调,比如 RTDB onDataChangedonCancelled(在 Android 中,但所有平台的逻辑相似)。同意保护其他演员,所以我在回答中更新了它。我显然是多语种,这意味着我在每种语言中都同样不习惯。 :-D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-06
  • 2016-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-16
  • 1970-01-01
相关资源
最近更新 更多