遍历Firebase中节点中的所有节点

Posted

技术标签:

【中文标题】遍历Firebase中节点中的所有节点【英文标题】:Iterating through all nodes in node in Firebase 【发布时间】:2017-02-07 21:31:20 【问题描述】:

我的示例结构如下所示:

我想将每个项目添加到我创建的项目数组中。所以你可以看到downloadListData函数只能从Apples下载信息,因为我不知道如何在不编写大量代码的情况下同时获取Apples、Bread和Eggs。我正在尝试循环和数组,但它没有用。此外,我正在分析 Internet 上的示例,但没有得到适用于我的应用程序的答案。

ListItem.swift:

import Foundation
import Firebase

struct ListItem
    var name : String!
    var addedBy : String!
    var completed : Bool!

    init(name: String, addedBy: String, completed: Bool)
        self.name = name
        self.addedBy = addedBy
        self.completed = completed
    

我的 ViewController.swift 的一部分:

import UIKit
import Firebase

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource 

    var rootRef : FIRDatabaseReference!
    var listDataRef : FIRDatabaseReference!

    var refHandle: UInt!

    var listItemsDownload = [ListItem]()

    //test vars
    var user : String!

    @IBOutlet weak var plusButton: UIButton!
    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() 
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        tableView.delegate = self
        tableView.dataSource = self
        user = "test@me.com"


        rootRef = FIRDatabase.database().reference()
        listDataRef = rootRef.child("listData")            

        downloadListData()
    

func numberOfSections(in tableView: UITableView) -> Int 
    return 1


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return listItemsDownload.count


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    if let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? CellData

        print("cellForRowAt")
        let items = listItemsDownload[indexPath.row]
        // testing the tableView            
        cell.nameLabel?.text = items.name

        
        return cell
     else
        print("else")
        return CellData()
    

func downloadListData()
    print(" ### DOWNLOAD ###")
    self.listDataRef.observe(FIRDataEventType.value, with:  snapshot in
        var downloadedName : String!
        var downloadedUser : String!
        var downloadedComplete : Bool!

        if let dict = snapshot.value as? Dictionary<String, Any>
            if let apples = dict["Apples"] as? Dictionary<String, Any>

                if let name = apples["name"] as? String
                    downloadedName = name
                

                if let user = apples["addedBy"] as? String
                    downloadedUser = user
                

                if let completed = apples["completed"] as? Bool
                    downloadedComplete = completed
                

                let item = ListItem(name: downloadedName, addedBy: downloadedUser, completed: downloadedComplete)

                self.listItemsDownload.append(item)

                self.tableView.reloadData()

            
        
    )

所以我可能只需要更改这一行来获得不同的值,而不仅仅是 Apples (if let apples = dict["Apples"] as? Dictionary&lt;String, Any&gt;

【问题讨论】:

【参考方案1】:

只需使用单独的方法,您可以使用不同的键调用,如下所示:

  func downloadListData()
    print(" ### DOWNLOAD ###")
    self.listDataRef.observe(FIRDataEventType.value, with:  snapshot in
        addAllItemsFromSnapshotWithKey(snapshot, key: "Apples")
        addAllItemsFromSnapshotWithKey(snapshot, key: "Bread")
        addAllItemsFromSnapshotWithKey(snapshot, key: "Eggs")
        // You need to reload your table view on the main thread, since it's an asynchronous call to firebase
        DispatchQueue.main.async 
          self.tableView.reloadData()  
        
    )
  

  func addAllItemsFromSnapshotWithKey(_ snapshot: FIRDataSnapshot, key: String) 
    var downloadedName : String!
    var downloadedUser : String!
    var downloadedComplete : Bool!

    if let dict = snapshot.value as? Dictionary<String, Any>
      if let values = dict[key] as? Dictionary<String, Any> 

        if let name = values["name"] as? String
          downloadedName = name
        

        if let user = values["addedBy"] as? String
          downloadedUser = user
        

        if let completed = values["completed"] as? Bool
          downloadedComplete = completed
        

        let item = ListItem(name: downloadedName, addedBy: downloadedUser, completed: downloadedComplete)

        self.listItemsDownload.append(item)

      
    
  

更新以获得更具可扩展性的解决方案。只需遍历所有键

 func downloadListData()
    print(" ### DOWNLOAD ###")
    self.listDataRef.observe(FIRDataEventType.value, with:  snapshot in
      var downloadedName : String!
      var downloadedUser : String!
      var downloadedComplete : Bool!

      if let dict = snapshot.value as? Dictionary<String, Any>

        for key in dict.keys 

          if let values = dict[key] as? Dictionary<String, Any> 

            if let name = values["name"] as? String
              downloadedName = name
            

            if let user = values["addedBy"] as? String
              downloadedUser = user
            

            if let completed = values["completed"] as? Bool
              downloadedComplete = completed
            

            let item = ListItem(name: downloadedName, addedBy: downloadedUser, completed: downloadedComplete)

            self.listItemsDownload.append(item)
          
        
        DispatchQueue.main.async 
          self.tableView.reloadData()
        
      
    )
  

【讨论】:

好的,但是如果我有更多数据呢?这似乎不是一个非常可扩展的解决方案。 更新了我的答案@codddeer123

以上是关于遍历Firebase中节点中的所有节点的主要内容,如果未能解决你的问题,请参考以下文章

使用 Github 包作为 npm 节点模块时的 Firebase 云功能部署问题

使用 android studio java Recycler 视图从 Firebase 实时数据库中删除一个节点

访问 Firebase 数据库中的多个节点

如何循环并获取firebase中嵌套节点的所有键?

如何在不从参考节点获取所有数据的情况下获取 Firebase 数据库中的随机键?

如果其中包含来自更多经过应用程序身份验证的用户的数据,我如何遍历Firebase表?