使用Firebase字典填充Swift数组

3

我正在尝试从Firebase获取数据并将其作为对象添加到Swift数组中,但每当我运行应用程序时,数组都会打印为空。当我在观察代码块内放置一个print语句时,每个钱包都像我想要的那样打印出来,但钱包从未被追加到数组中。

var purses = [Purse]()

override func viewDidLoad() {
    fetchPurse(completion: {print(self.purses.count)})
}

func fetchPurse(completion: @escaping () -> ()){
    let ref = FIRDatabase.database().reference(fromURL: "https://test-database-ba3a2.firebaseio.com/")
    let user = (FIRAuth.auth()?.currentUser?.uid)!
    let userRef = ref.child("users").child(user).child("devices")

    userRef.observe(.childAdded, with: { (snapshot) in
        if let dictionary = snapshot.value as? [String: AnyObject]{
            let purse = Purse()
            purse.setValuesForKeys(dictionary)
            self.purses.append(purse)
            completion()
        }
    }, withCancel: nil)
}

你想在哪里打印这个数组?由于你是在异步函数中填充这个数组,所以如果你试图在完成处理程序之外观察它的值,你很可能会在数组被填充之前就打印出来。 - Dávid Pásztor
我正在另一个函数中调用数组,并尝试使用.count方法根据钱包数量加载一定数量的表格单元格以供我的表视图使用。 - Ben Cavenagh
fetchPurse() 应该有一个完成处理程序,你应该从完成处理程序中调用你的其他函数。 - Dávid Pásztor
你能告诉我哪里可以学习如何做到这一点吗?我从未真正使用过完成处理程序,也不知道如何将其添加到我的函数中。 - Ben Cavenagh
1个回答

2
这似乎是对异步方法工作原理的误解。
如果您使用以下代码:
//at this point purses is empty..
fetchPurse()
print("purses count = \(purses.count)")

您将始终看到一个空的钱包数组。
问题在于`fetchPurse()`函数使用了Firebase函数`observe`,该函数是异步的。它请求Firebase在添加新条目时运行您传递作为`with:`闭包的代码。`observe`函数立即返回,并在Firebase添加新子对象时,将其传递给它的闭包调用。
因此,您的`fetchPurse()`函数在新的钱包对象添加到您的钱包数组之前也会返回。
正如@DávidPásztor在他的评论中所说,您应该重构`fetchPurse`以采取完成处理程序,在更新钱包数组时调用该处理程序:
func fetchPurse(completion: () -> ){
    let ref = FIRDatabase.database().reference(fromURL: "https://test-database-ba3a2.firebaseio.com/")
    let user = (FIRAuth.auth()?.currentUser?.uid)!
    let userRef = ref.child("users").child(user).child("devices")

    userRef.observe(.childAdded, with: { (snapshot) in
        if let dictionary = snapshot.value as? [String: AnyObject]{
            let purse = Purse()
            purse.setValuesForKeys(dictionary)
            self.purses.append(purse)
            //This is the new line that calls your new completion handler
            completion()
        }
    }, withCancel: nil)
}

然后你可以这样调用它:

fetchPurse(completion: {
  print("purses count = \(purses.count)")
}

我更新了问题,展示了我如何实现你的代码,但仍然显示空数组。我也包括了我调用fetchPurse函数的位置。 - Ben Cavenagh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接