Swift函数返回空数据

时间:2019-09-09 19:03:19

标签: swift

我是Swift编码的新手,我一直在寻找解决该问题的方法,但至今仍找不到解决我问题的方法。

我正在使用一个函数从Firebase返回一些数据。经过许多错误和大量研究之后,我设法在不引发错误的情况下使函数“正常运行”,但是返回的数据为空。本质上,我在调用函数时试图返回多个值并将它们保存在数组中。

数据从Firebase正常返回,当我在设置变量后立即打印出变量时,它将正确打印,但是当我在返回函数之前执行相同操作时,它将返回空白。如果我尝试在设置数据后立即返回该函数,则会收到错误“ void函数中的非预期非空返回值”。

这是完整的代码:

func loadClientData(client_id: String) -> (address_1: String, address_2: String, city: String, company_name: String, contact_name: String, county: String, email: String, phone: String, postcode: String, country: String) {
        let db = Firestore.firestore()
        let userID : String = (Auth.auth().currentUser!.uid)

        print("\(userID)/clients/existing/\(client_id)")

        let docRef = db.collection("\(userID)/clients/existing/").document(client_id)

        var address_1 = ""
        var address_2 = ""
        var city = ""
        var company_name = ""
        var contact_name = ""
        var county = ""
        var email = ""
        var phone = ""
        var postcode = ""
        var country = ""

        docRef.getDocument { (document, error) in
            if let document = document, document.exists {

                let data = document.data()

                address_1 = data?["address_1"] as? String ?? ""
                address_2 = data?["address_2"] as? String ?? ""
                city = data?["city"] as? String ?? ""
                company_name = data?["company_name"] as? String ?? ""
                contact_name = data?["contact_name"] as? String ?? ""
                county = data?["county"] as? String ?? ""
                email = data?["email"] as? String ?? ""
                phone = data?["phone"] as? String ?? ""
                postcode = data?["postcode"] as? String ?? ""
                country = data?["country"] as? String ?? ""

                print("Company name is \(company_name)") // <---- THIS prints out the company name

            } else {
                print("client does not exist")
                return
            }
        }


        print("Company name is \(company_name)") // <---- THIS prints the company name as blank

        return (address_1: address_1, address_2: address_2, city: city, company_name: company_name, contact_name: contact_name, county: county, email: email, phone: phone, postcode: postcode, country: country)
    }

被这样称呼:

let companyInfo = loadClientData(client_id: self.items[indexPath.item].company)

        print(companyInfo)

并打印出以下内容:

  

(地址_1:“”,地址_2:“”,城市:“”,公司名称:“”,   contact_name:“”,县:“”,电子邮件:“”,电话:“”,邮政编码:“”,   国家:“”)

谢谢您的输入。

2 个答案:

答案 0 :(得分:5)

此网站上有many个问题,它们与您的问题基本相同,因此您应该查看一下。为避免重复,我将简单说明一下,但敦促您阅读类似的问题。

简而言之,发生的事情是loadClientData 异步获取数据,这意味着它发生在后台,而其他内容发生在前台。前台内容包括调用loadClientData并将其打印出来的代码。 前景材料不会等待背景材料完成。

您什么也没得到,因为到print(companyInfo)时,背景材料还没有完成处理。

  

真实世界示例:

     

你妈妈要你去买柠檬做晚餐。

     

她开始做饭,但没有柠檬!

     

为什么?因为您还没有从超市回来,而您的妈妈没有等。

如果要让前台等待,则有很多选择,可以通过查看other similar questions来考虑。

答案 1 :(得分:1)

您需要重构函数以不返回任何内容,并使用完成处理程序。完成处理程序是调用者传递给您的函数的代码块。结果可用后,您的函数将调用完成处理程序。这是Swift中常见的编码模式,您的firebase getDocument()调用被编写为使用完成处理程序。

搜索Swift completion handler design pattern以了解更多信息。

**注意:

使用完成处理程序只是执行此操作的一种方法。您也可以使用委托设计模式,但是完成处理程序是处理异步事件的更现代的方式,也是我建议处理问题的方式。