通过嵌套的Firebase数据循环填充数组Swift [英] Fill an array through a nested Firebase data loop Swift

查看:85
本文介绍了通过嵌套的Firebase数据循环填充数组Swift的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过从一个Firebase节点获取值来填充数组,并使用这些值从另一个Firebase节点获取信息.我该怎么办?

I want to fill an array by fetching values from one firebase node and use those values to fetch information from a different firebase node. How do I do that?

这是我的Firebase数据库的样子:

This is what my firebase database looks like:

{
  "MainTree" : {
    "subTree1" : {
      "JiRtkpIFLVFNgmNBpMj" : {
        "PiRterKFLVFNgmFFFtu" : "PiRterKFLVFNgmFFFtu"
        "TfRterKFLVFNgmFGFre" : "TfRterKFLVFNgmFGFre",
        "X4RterKFLVFNgmaDFca" : "X4RterKFLVFNgmaDFca"
        }
      },
    "subTree2" : {
        "PiRterKFLVFNgmFFFtu" : {
        "username" : "user1",
        "uid" : "PiRterKFLVFNgmFFFtu"
        },
        "TfRterKFLVFNgmFGFre" : {
        "username" : "user2",
        "uid" : "TfRterKFLVFNgmFGFre"
        },
        "X4RterKFLVFNgmaDFca" : {
        "username" : "user3",
        "uid" : "X4RterKFLVFNgmaDFca"
        }
    }
    }
}

我的功能

func fetchAllInformation(uid: String, completion: @escaping ([UserData]) -> (), withCancel cancel: ((Error) -> ())?) {

    let ref = Database.database().reference().child("MainTree").child("subTree1").child(uid)
    ref.observeSingleEvent(of: .value, with: { (snapshot) in

        if snapshot.exists(){
            guard let dictionaries = snapshot.value as? [String: Any] else {
                completion([])
                return
            }
            var Values = [UserData]()
            let group = DispatchGroup()
            dictionaries.forEach({ (key, value) in
                group.enter()
                let ref = Database.database().reference().child("MainTree").child("subTree2").child(key)
                ref.observeSingleEvent(of: .value, with: { (snapshot) in
                    guard let userDictionary2 = snapshot.value as? [String: Any] else { return }
                    let user = UserData(dictionary: userDictionary2)
                    Values.append(user)
                }) { (err) in
                    print("Failed to fetch all user data from database:", (err))
                    cancel?(err)
                }
            })
            group.notify(queue: .main) {
                print("loop done")
                completion(Values)
            }
        }
    }) { (err) in
        print("Failed to fetch all data from database:", (err))
        cancel?(err)
    }
}

我的通话功能:

fetchAllInformation(uid: "JiRtkpIFLVFNgmNBpMj", completion: { (userdata) in
                print("fetched all userdata! : ",userdata)

            }) { (err) in
                print("data fetch failed")
            }

我的数据结构

struct UserData {

let uid: String
let username: String

init(dictionary: [String: Any]) {
    self.uid = dictionary["id"] as? String ?? ""
    self.username = dictionary["username"] as? String ?? ""
    }
}

对异步代码可能是一种误解.现在的问题是数组变成空的.

It might be a misunderstanding with asynchronous code. Right now the problem is that the array is turning up empty.

推荐答案

我认为您要问的是如何遍历一系列节点,如何从该节点获取另一个节点的子键,然后从另一个节点读取数据这些键为基础的节点.

I think what's you're asking is how to iterate over a series of nodes, getting another nodes child keys from that node, then reading the data from the other node based on those keys.

让我从一个Firebase结构开始,该结构应该有助于阐明

Let me start with a Firebase structure that should help clarify

MainTree
   subTree1
      some_node
         subTree2_0: true
         subTree2_1: true
         subTree2_2: true
   subTree2
      subTree2_0:
          user_name: "Larry"
      subTree2_1:
          user_name: "Moe"
      subTree2_1:
          user_name: "Curly"

那应该符合问题的结构.

That should match up to the structure in the question.

我们将遍历MainTree/subTree1/some_node中的子节点,以获取要从subTree2中读取的节点.我不知道与其余数据有关的some_node是什么,所以我将其称为... some_node.

We're going to iterate over the child nodes located in MainTree/subTree1/some_node to get the nodes we want to read from subTree2. I didn't know what some_node was in respect to the rest of the data so I just called it... some_node.

第一部分代码立即读取subTree1节点的子节点,然后对其进行迭代以获取每个子键-该子键(例如subTree2_0)对应于subTree2中的一个子节点

This first section of code reads the subTree1 node child nodes at once, then iterates over them to get each child key - that child key (e.g. subTree2_0) corresponds to a child node in subTree2

func readMainTree() {
    let mainTreeRef = self.ref.child("MainTree")
    let subTree1Ref = mainTreeRef.child("subTree1")
    let someNodeRef = subTree1Ref.child("some_node")
    someNodeRef.observeSingleEvent(of: .value, with: { snapshot in
        let childNodes = snapshot.children.allObjects as! [DataSnapshot]
        for childSnap in childNodes {
            self.readSubTree2At(node: childSnap.key)
        }
    })
}

在for..loop内,我们获得每个子键,并将其传递给读取子数据(用户名)并打印出来的函数.

Within the for..loop, we get each child key and pass that to the function that reads the child data (user_name) and prints it out.

func readSubTree2At(node: String) {
    let mainTreeRef = self.ref.child("MainTree")
    let subTree2Ref = mainTreeRef.child("subTree2")
    let childRef = subTree2Ref.child(node)
    childRef.observeSingleEvent(of: .value, with: { snapshot in
        let userName = snapshot.childSnapshot(forPath: "user_name").value as? String ?? "No Name"
        print(userName)
    })
}

,输出为:

Larry
Mo
Curly

如果需要,可以将dispatchGroup放入混合中.这是使用DispatchGroup的解决方案

You could throw a dispatchGroup into the mix if you want.. here's a solution using a DispatchGroup

func readMainTreeWithDispatch() {
    let mainTreeRef = self.ref.child("MainTree")
    let subTree1Ref = mainTreeRef.child("subTree1")
    let someNodeRef = subTree1Ref.child("some_node")
    someNodeRef.observeSingleEvent(of: .value, with: { snapshot in
        let childNodes = snapshot.children.allObjects as! [DataSnapshot]

        let myGroup = DispatchGroup()

        for childSnap in childNodes {
            let mainTreeRef = self.ref.child("MainTree")
            let subTree2Ref = mainTreeRef.child("subTree2")
            let childRef = subTree2Ref.child(childSnap.key)

            myGroup.enter()
            childRef.observeSingleEvent(of: .value, with: { snapshot in
                let userName = snapshot.childSnapshot(forPath: "user_name").value as? String ?? "No Name"
                print(userName)
                myGroup.leave()
            })
        }

        myGroup.notify(queue: .main) {
            print("Finished reading all user names.")
        }
    })
}

和输出

Larry
Mo
Curly
Finished reading all user names.

这篇关于通过嵌套的Firebase数据循环填充数组Swift的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆