为什么我不能修改在闭包外声明的变量?

Why can I not modify a variable declared outside a closure?

每次我测试我的代码时,都会向 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
}

这是因为数据是从 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")

当您 运行 此代码时,它会打印:

Before starting to get data

After starting to get data

Got 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{

    }
}

另见:

  • ,这也显示了使用自定义闭包将您自己的代码保留在 getDocument 闭包之外。
  • ,显示使用调度组来保存代码