Заполните массив через вложенные данные Firebase l oop Swift - PullRequest
0 голосов
/ 15 января 2020

Я хочу заполнить массив путем извлечения значений из одного узла Firebase и использовать эти значения для извлечения информации из другого узла Firebase. Как мне это сделать?

Вот так выглядит моя база данных firebase:

{
  "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 ?? ""
    }
}

Это может быть недоразумение с асинхронным кодом. Сейчас проблема в том, что массив становится пустым.

1 Ответ

2 голосов
/ 15 января 2020

Я думаю, что вы спрашиваете, как выполнить итерацию по ряду узлов, получить дочерние ключи других узлов от этого узла, а затем прочитать данные из другого узла на основе этих ключей.

Позвольте мне Начнем со структуры Firebase, которая должна помочь прояснить

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"

Это должно соответствовать структуре в вопросе.

Мы собираемся перебрать дочерние узлы, расположенные в MainTree / subTree1 / some_node, чтобы получить узлы, которые мы хотим прочитать из subTree2. Я не знал, каков был some_node по отношению к остальным данным, поэтому я просто назвал его ... some_node.

Этот первый раздел кода сразу читает дочерние узлы узла subTree1, затем перебирает их чтобы получить каждый дочерний ключ - этот дочерний ключ (например, subTree2_0) соответствует дочернему узлу в 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..l oop мы получаем каждый дочерний ключ и передаем его функции который читает дочерние данные (имя_пользователя) и распечатывает их.

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

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.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...