【问题标题】:How to read data from firebase and append it to an array如何从firebase读取数据并将其附加到数组
【发布时间】:2020-06-05 05:56:36
【问题描述】:

我有一个 userImages 集合,我正在尝试从中读取数据并将其附加到我的 imgUrls 数组中。

这是我从数据库中读取数据并尝试将其附加到我的数组的代码。不幸的是,我不断收到错误,因为数组显然是空的。

override func viewDidLoad() {
var ref: DatabaseReference!
        let userID = Auth.auth().currentUser?.uid       //holds the current user uid

        ref = Database.database().reference()

        var imgUrls = [String]()        //array to hold the image urls from the userImages collection

        ref.child("userImages").child(userID!).observeSingleEvent(of: .value) { (snapshot) in     //read from userImages collection only from the subcollection where the
            guard let dict = snapshot.value as? [String: Any] else { return }                       //document Id equals the current user uid. Create a dictionary from the
                                                                                                    //snapshot values

            let values = dict.values        //holds the values from the dictionary

            for value in values {                           //for loop to go through each value from the dictionary
                imgUrls.append((value as? String)!)       //and append to the imgUrls array
            }
        }

        testLabel.text = imgUrls[0]     //I used this to test, but i get an error saying the array is empty
}

我之前发过一个问题,但是太复杂了我决定删除它并重新发布它更简单。

非常感谢任何帮助!

【问题讨论】:

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


    【解决方案1】:

    您在 testLabel.text 中没有得到任何内容的原因是:

         ref.child("userImages").child(userID!).observeSingleEvent(of: .value) { (snapshot) in     //read from userImages collection only from the subcollection where the
    
         ...
    
         }
    

    是一个被调用的异步函数。那就是将来有时会这样做。

    但是你的:

      testLabel.text = imgUrls[0]     //I used this to test, but i get an error saying the array is empty
    

    不在此调用范围内。因此“imgUrls”中的结果尚不可用。 将此行放在函数中或等到它完成后再使用结果。

    【讨论】:

    • 我没有把它放在问题中,但是整个代码都在 viewDidLoad() 函数中。我是 Swift 和 firebase 的新手。我大约一周半或两周前才开始使用它,所以我仍然掌握它。我目前对 SQL 数据库比较熟悉。
    • 一切顺利,Swift 和 firebase,这是一个很好的组合。 Firebase 基本上是异步的。确实需要对此有一个很好的理解。在此有一篇不错的 swift 相关文章:firebase.googleblog.com/2018/07/…
    【解决方案2】:

    您尝试在执行 observeSingleEvent 闭包之前使用数组。对 Firebase 的所有观察调用都是异步的。这意味着你的测试代码在闭包之前执行并且数组仍然是空的。

    ref.child("userImages").child(userID!).observeSingleEvent(of: .value) { snapshot in
    
        // this closure is executed later
    
        guard let dict = snapshot.value as? [String: Any] else { return }
    
        let values = dict.values
    
        for value in values {
            imgUrls.append((value as? String)!)
        }
    
        // your test code should bee here
    }
    
    // this is executed before closure and the array is empty
    testLabel.text = imgUrls[0]
    

    因此,您会收到错误消息。您需要将测试代码添加到闭包中。

    但是,还有另一个问题。异步调用(它们的闭包)在后台线程上执行。

    ref.child("userImages").child(userID!).observeSingleEvent(of: .value) { snapshot in
    
      // this is executed on the background thread
    
    }
    

    但是,所有用户界面调用都必须在主线程上执行。还要通过调用主线程来包装您的测试代码,否则您将不会在用户界面中看到结果。

    DispatchQueue.main.async {
    
      // this code is executed on the main thread
      // all UI code must be executed on the main thread
    
    }
    
    

    编辑后,您的代码可能如下所示:

    
    override func viewDidLoad() {
            var ref: DatabaseReference!
            let userID = Auth.auth().currentUser?.lid
    
            ref = Database.database().reference()
    
            var imgUrls = [String]()
    
            ref.child("userImages").child(userID!).observeSingleEvent(of: .value) { snapshot in
                guard let dict = snapshot.value as? [String: Any] else { return }
    
                let values = dict.values
    
                for value in values {
                    imgUrls.append((value as? String)!)
                }
    
                DispatchQueue.main.async {
                    testLabel.text = imgUrls[0]
                }
            }
    }
    
    

    【讨论】:

    • 非常感谢您的回复!不幸的是,它仍然没有工作。这太奇怪了
    • @EverNolasco 尝试在最后一条语句下添加 testLabel.setNeedsDisplay(),例如 DispatchQueue.main.async { testLabel.text = imgUrls[0] testLabel.setNeedsDisplay() }
    猜你喜欢
    • 2021-09-20
    • 2020-02-16
    • 2021-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多