如何让类中的初始化方法等待 Firestore 在 Swift 4 中完成?
Posted
技术标签:
【中文标题】如何让类中的初始化方法等待 Firestore 在 Swift 4 中完成?【英文标题】:How to make initializer method in class wait for Firestore to finish in Swift 4? 【发布时间】:2019-03-03 02:51:01 【问题描述】:我正在调用一个函数,该函数初始化一个类,并且在该类中我有一个初始化方法,该方法向 Firestore 发出请求。我在那个类中也有一个变量,一旦我完成了对数据库的循环,我将这个 self.variable 更改为等于我刚刚创建的任何内容。出于某种原因,我无法完成此操作,并且当我初始化我的类对象时,变量的值永远不会改变。
(假设 User 类只包含姓名和年龄)
这是我调用函数并初始化对象的地方
fileprivate func fetch()
let homeObject = Home()
print (homeObject.user.count)
//count prints out as 0
print (homeObject.test)
//test prints out as 2 .. should be 3 but I'm not sure why?
这是 Home 的类
class Home
var user: [User] = []
var test = 1
required init()
self.test = 2
var userLoop = [User]()
let db = Firestore.firestore()
db.collection("users").getDocuments() (querySnapshot, err) in
if let err = err
print("Error getting documents: \(err)")
else
for document in querySnapshot!.documents
print("\(document.documentID) => \(document.data())")
let name_data = document.data()["name"]! as! String
let age_data = document.data()["age"]! as! String
let userTemp = User(name: name_data , age: age_data)
self.test = 3
userLoop.append(userTemp)
self.user = userLoop
由于某种原因,test 能够更改为数字 2,但我相信这个初始化方法没有完成,因为它没有转到数字 3(如您在上面看到的,稍后在初始化函数中我将其更改为数字 3)。我非常感谢您的帮助,现在已经坚持了几个小时!
【问题讨论】:
“异步”是什么意思? 也许您可以将最终需要初始化的东西声明为可选变量。那么,在一个成功响应的完成块中,那么你可以初始化它吗? Firebase 是异步的;因此这一行print (homeObject.user.count)
在 firebase 关闭之前执行,因为代码比互联网快。这个问题之前已经被问过很多次了。 this answer 应该增加一些清晰度。在[firebase]firebase is asynchronous
上搜索并阅读问答。
@Jay 我看到了这个解决方案,它与我的问题有点不同。是的,我可以在我的 Home 类中所需的 init 方法中做一些事情,但是我需要在创建 home 之后,就在此期间获取这些信息。此外,它仅在我将所需的 init 方法更改为函数方法并在我的 fetch 函数中调用它时才有效。
问题是你试图像函数一样调用firebase,但这是行不通的。需要做的是首先从 Firestore 获取数据,然后使用该数据初始化您的 Home var。所以调用 Firestore 来获取所需的文件,然后用它们初始化你的 var let home = HomeClass(initWithDocuments: documents)
【参考方案1】:
使用如下完成块初始化Home
:
class Home
var user: [User] = []
required init(with block: (Home)->Void)
var userLoop = [User]()
let db = Firestore.firestore()
db.collection("users").getDocuments() (querySnapshot, err) in
if let err = err
print("Error getting documents: \(err)")
else
for document in querySnapshot!.documents
print("\(document.documentID) => \(document.data())")
let name_data = document.data()["name"]! as! String
let age_data = document.data()["age"]! as! String
let userTemp = User(name: name_data , age: age_data)
userLoop.append(userTemp)
self.user = userLoop
block(self)
并将其称为:
var home = Home (home) in
//set your properties if needed.
【讨论】:
嗯,这并没有真正提供解决方案。虽然 home 中的 var 可以在var home = Home
闭包中初始化,但之后的任何代码都将在 before home 被初始化之前执行。通过向类添加 var 来复制问题,在 var home = Home
中分配一个值,然后添加一个 print 语句以在闭包后打印 var。它在类闭包中的代码之前执行时打印一个空字符串,这仍然与问题中的问题相同。此外,block(self)
会抛出错误 关闭使用非转义参数 'block' 可能会允许它转义以上是关于如何让类中的初始化方法等待 Firestore 在 Swift 4 中完成?的主要内容,如果未能解决你的问题,请参考以下文章
Firestore,Flutter,Async:方法不等待异步方法完成