【问题标题】:How to add values to a dictionary while inside of a function (with Firebase)如何在函数内部向字典添加值(使用 Firebase)
【发布时间】:2017-07-12 03:21:09
【问题描述】:

我在类文件中声明了一个字典,如下所示:

var myDict: [Int: String] = [:]

我还做了一个函数来更改字典中的值:

func firebaseToDictionary() {
    let uid = FIRAuth.auth()?.currentUser?.uid
    let infoRef = FIRDatabase.database().reference().child("users").child(uid!).child("info")

    infoRef.observe(FIRDataEventType.value, with: { (snapshot) in
        let postDict = snapshot.value as? [String: String]
        for item in postDict! {

            let theString = item.value["FirebaseString"]
            let theNumber = item.value["FirebaseInt"]                

            self.myDict[theNumber] = theString

            //First Print
            print(myDict)
        }
    })
    //Second Print
    print(myDict)
}

//First Print 处,字典包含新值并且看起来不错,但//Second Print 显示字典创建时的样子;作为[:]//Second Print 实际上在 //First Print 之前出现在终端中

为什么我的字典在函数内部更改后仍显示为 [:]?

【问题讨论】:

    标签: swift dictionary firebase firebase-realtime-database firebase-authentication


    【解决方案1】:

    您的代码以正确的方式运行。你有一个同步函数,它在后台线程中获取数据

    infoRef.observe(FIRDataEventType.value, with: { (snapshot) in
        let postDict = snapshot.value as? [String: String]
        for item in postDict! {
    
            let theString = item.value["FirebaseString"]
            let theNumber = item.value["FirebaseInt"]                
    
            self.myDict[theNumber] = theString
    
            //First Print
            print(myDict)
        }
    })
    

    在您从远程数据库接收到数据后,将调用此闭包中的代码。因此,如果您在此异步调用之后有另一个 print(myDict),它将首先打印出来,其中包含原始值。然后当异步调用完成并执行闭包内的代码时,会触发第一个print(myDict),然后使用新更新的数据

    话虽如此,您的新数组在回调您的闭包之前不会加载数据。从您的代码中,您似乎有一个表格视图,显示该数组上的数据库。所以你必须等到数组获取数据然后重新加载表视图。因此,您需要将该代码带到闭包的末尾。但是,在 swift 中,您不能直接从后端线程更新 UIElement,就像这个回调函数一样。所以在你填满你的数组之后,你需要以这种方式在主线程中运行表视图重新加载代码

    infoRef.observe(FIRDataEventType.value, with: { (snapshot) in
        let postDict = snapshot.value as? [String: String]
        for item in postDict! {
    
            let theString = item.value["FirebaseString"]
            let theNumber = item.value["FirebaseInt"]                
    
            self.myDict[theNumber] = theString
    
            //First Print
            print(myDict)
            DispatchQueue.main.async {
               tableView.reloadData()
            }
        }
    })
    

    【讨论】:

    • 不起作用,字典在除//First Print以外的任何位置打印时仍显示为 [:]
    • @BigJohnson 正如我所提到的,您的第二次打印实际上是首先执行的,然后是第一次打印。因此,在您的情况下,我们仅期望从第一次打印中获得值。所以我要求你做的是将数据重新加载功能移到第一个打印下,你实际上是从服务器调用中获取数据
    • 目前,tableView 没有任何内容。一旦我让字典正常工作(不显示为 [:]),我将对它进行排序并将其放入一个数组中,然后该数组将显示在 tableView 中。因此,此时将 tableView.reloadData() 放入 dispatchQueue.main.async 内无济于事,因为在字典正常工作之前,我无法设置 tableView。
    • @BigJohnson 当然,因此您需要对字典进行排序并将其放入另一个数组中。这些操作应该在您在封盖内的第一个打印件下完成,您明白了吧?你知道第二次打印是没有用的,对吧?
    • 是的,我明白这一点。但是字典仍然没有值。对于 tableView 函数 numberOfRowsInSection,我让它 return myDict.count 并且 tableView 中没有单元格。所以由于某种原因,字典仍然没有值,即使我的函数 firebaseToDictionary() 为它提供了值。
    【解决方案2】:

    从您的代码来看,infoRef.observe() 似乎是一个异步任务,因此如果您在此之后有一个代码,它可能会在异步任务执行之前执行。您可以按如下方式更改代码:

    func firebaseToDictionary() {
        let uid = FIRAuth.auth()?.currentUser?.uid
        let infoRef = FIRDatabase.database().reference().child("users").child(uid!).child("info")
    
        infoRef.observe(FIRDataEventType.value, with: { (snapshot) in
            let postDict = snapshot.value as? [String: String]
            for item in postDict! {
    
                let theString = item.value["FirebaseString"]
                let theNumber = item.value["FirebaseInt"]                
    
                self.myDict[theNumber] = theString
    
                //First Print
                print(myDict)
                DispatchQueue.main.async {
                   tableView.reloadData()
                }
            }
        })
    }
    

    您在观察之后添加的任何内容都可以立即执行,而无需等待观察部分完成。因此,请确保您在完成后要执行某些操作,请在块内执行。

    【讨论】:

    • 没有修复,当我在别处打印时,字典仍然显示为 [:]
    • 您在哪里打印?你是在第一次打印完成后打印它吗?当您的观察方法是异步块时,您为什么要在其他地方打印。你应该等待它完成
    猜你喜欢
    • 2014-09-14
    • 1970-01-01
    • 2016-10-29
    • 2018-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    • 2019-05-02
    相关资源
    最近更新 更多