Проблема параллелизма при извлечении данных из Firebase для отображения в виде таблицы - PullRequest
2 голосов
/ 26 января 2020

В настоящее время я пытаюсь получить данные пользователя из моей базы данных реального времени (Firebase) в Swift и отобразить имена пользователей в виде таблицы. У меня есть следующая функция для извлечения всех пользователей из базы данных, которая находится в главном классе моего файла (переменная users, к которой я добавляю, уже была инициирована как пустой массив строк).

func retrieveAllUsers(){

        //hold all users
        var userFullName = ""

        self.usersReference.observeSingleEvent(of: .value, with: {(snapshot) in
        // if marker ID has children it means this marker has already been created
            //go in User ID uid
            if snapshot.hasChildren() {
                // go through all user ids
                for child in snapshot.children {
                    //initialize a user name and first name
                    var userFirstName = ""
                    var userLastName = ""
                    let subSnap = child as! DataSnapshot
                    //get child key with format UserID: uid
                    let key = subSnap.key
                    // go inside User ID to retrieve name and first name of every user
                    DispatchQueue.main.async {
                        self.usersReference.child(key).observeSingleEvent(of: .value, with: { (snapshot2) in
                            // go through user parammters to only retrieve his name and first name
                            for grandChild in snapshot2.children {
                                let nameGatherer = grandChild as! DataSnapshot
                                if nameGatherer.key == "First Name:"{
                                    userFirstName = nameGatherer.value as! String
                                }
                                if nameGatherer.key == "Last Name:"{
                                    userLastName = nameGatherer.value as! String
                                }
                            }//end of loop inside user parameters
                            //add his full name to the list of users which we will then filter later on
                            userFullName = userFirstName + userLastName
                            self.users.append(userFullName)
                            self.tableView.reloadData()
                            print("IN CLOSURE: \(self.users)")
                        })// end of observation of one user parameters
                    }//end of dispatch async
                print("OUTSIDE CLOSURE1: \(self.users)")
                }//end of looking inside the user ID node
            print("OUTSIDE CLOSURE2: \(self.users)")
            }//end of if there are users children
        print("OUTSIDE CLOSURE3: \(self.users)")
        })//end of observation of users reference
        print("OUTSIDE CLOSURE4: \(self.users)")
    }

И в моем viewDidLoad у меня есть

retrieveAllUsers()
print("USERS:\(self.users)")
tableView.reloadData()

Я пытался использовать параллелизм с Dispatchmain.asyn c (это мой первый раз, когда я выполняю параллелизм в моих программах). Тем не менее, это не похоже на работу, так как печать в моем viewDidLoad появляется первой, а пользователи пустые, следовательно, она не отображается в моем табличном представлении, и приходит печать ** print ("OUTSIDE CLOSURE1: (self.users)") ** последний с массивом, содержащим правильную информацию о пользователе.

Может ли кто-нибудь помочь мне получить правильную информацию о пользователе, которая будет отображаться в моем табличном представлении? Я действительно ценю это. Большое спасибо! Anthony

1 Ответ

1 голос
/ 26 января 2020

Ваша проблема вызвана тем, что ваш звонок на self.tableView.reloadData() фактически находится внутри обратного вызова Firebase с вашими данными. Этот обратный вызов не гарантированно находится в основном потоке, и все операции пользовательского интерфейса должны выполняться в основном потоке, всегда . Вам нужно обернуть вызов, чтобы перезагрузить таблицу внутри DispatchQueue.main.async напрямую (не вложенной в другой вызов), чтобы убедиться, что он вызывается в главном потоке.

Вы также не делаете нужно вызвать вложенный вызов внутри DispatchQueue.main.async. Смотрите мой пример:

func retrieveAllUsers(){

        //hold all users
        var userFullName = ""

        self.usersReference.observeSingleEvent(of: .value, with: {(snapshot) in
        // if marker ID has children it means this marker has already been created
            //go in User ID uid
            if snapshot.hasChildren() {
                // go through all user ids
                for child in snapshot.children {
                    //initialize a user name and first name
                    var userFirstName = ""
                    var userLastName = ""
                    let subSnap = child as! DataSnapshot
                    //get child key with format UserID: uid
                    let key = subSnap.key
                    // go inside User ID to retrieve name and first name of every user

                        self.usersReference.child(key).observeSingleEvent(of: .value, with: { (snapshot2) in
                            // go through user parammters to only retrieve his name and first name
                            for grandChild in snapshot2.children {
                                let nameGatherer = grandChild as! DataSnapshot
                                if nameGatherer.key == "First Name:"{
                                    userFirstName = nameGatherer.value as! String
                                }
                                if nameGatherer.key == "Last Name:"{
                                    userLastName = nameGatherer.value as! String
                                }
                            }//end of loop inside user parameters
                            //add his full name to the list of users which we will then filter later on
                            userFullName = userFirstName + userLastName
                            self.users.append(userFullName)
                            DispatchQueue.main.async {
                                self.tableView.reloadData()
                            }
                            print("IN CLOSURE: \(self.users)")
                        })// end of observation of one user parameters

                print("OUTSIDE CLOSURE1: \(self.users)")
                }//end of looking inside the user ID node
            print("OUTSIDE CLOSURE2: \(self.users)")
            }//end of if there are users children
        print("OUTSIDE CLOSURE3: \(self.users)")
        })//end of observation of users reference
        print("OUTSIDE CLOSURE4: \(self.users)")
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...