Can';t在if-else,Swift中更改变量

Can';t在if-else,Swift中更改变量,swift,asynchronous,Swift,Asynchronous,我在iOS应用程序中使用Firebase,我创建了一个函数,从Firestore数据库返回一个值。问题是变量val在if-else构造后不会改变 func getData(collection: String, doc: String, key: String) -> String { var val = "Simple string" var db: Firestore! let settings = FirestoreSettings() Fires

我在iOS应用程序中使用Firebase,我创建了一个函数,从Firestore数据库返回一个值。问题是变量val在if-else构造后不会改变

func getData(collection: String, doc: String, key: String) -> String {

    var val = "Simple string"

    var db: Firestore!
    let settings = FirestoreSettings()
    Firestore.firestore().settings = settings
    db = Firestore.firestore()

    let docRef = db.collection(collection).document(doc)
    docRef.getDocument { (document, error) in
        if let document = document, document.exists {
            val = (document.get(key) as! String)
            print(val)
        } else {
            val = "ERROR"
            print("Document does not exist")
        }
    }
    return val
}
这个函数必须从Firebase返回值(我可以通过print(val)看到它),但最后它返回初始值Simple string


我想我应该使用闭包来捕获if-else构造中的值,但我不知道如何做到这一点。

将代码分为以下三部分:

#1
docRef.getDocument { (document, error) in
    #2
}
#3
虽然不能保证,但执行顺序可能是#1->#3->#2:

  • 初始化并调用
    getDocument
    #1
  • 返回
    val
    ,它是
    简单字符串
    #3
  • 连接到服务器,获取文档,调用#2
因此,返回的值将是
简单字符串
。因为#2将异步执行

正确的方法是:

func getData(
     collection: String,
     doc: String, 
     key: String,
     handler: @escaping (String) -> Void
   ) {

   #1 

   docRef.getDocument { (document, error) in ...

      if... else...

      callback(result)
   }
}
使用将类似于:

getData(collection: .., doc: .., key: ..) { val in
    print(val)
}

问题是块是异步执行的,因此函数在执行响应块之前返回。我建议您更改函数的结构,类似这样的内容

func getData(fromCollection collection: String, doc: String, key: String, completion: @escaping (String?, Error?) -> Void) {
    var db: Firestore!
    let settings = FirestoreSettings()
    Firestore.firestore().settings = settings
    db = Firestore.firestore()

    let docRef = db.collection(collection).document(doc)
    docRef.getDocument { (document, error) in
        if let document = document,
            let val = document.get(key),
            document.exists {
            completion(val, nil)
        } else {
            completion(nil, error)
        }
    }
}

getDocument
异步工作时,此函数不能返回值。您需要一个完成处理程序。这个问题几乎每周都有人问。非常感谢!你能告诉我如何调用这个函数并返回一些值吗?