Как получить данные о пожарном депо и заполнить строки / разделы таблиц в словаре? - PullRequest
2 голосов
/ 29 апреля 2020

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

dataDict = ["Monday": ["Chest", "Arms"], "Wednsday": ["Legs", "Arms"], "Tuesday": ["Back"]]

Честно говоря Я даже не уверен, должен ли я хранить данные внутри словаря, как я это делал. Это неправильно делать это? Кроме того, поскольку данные извлекаются асинхронно, как я могу заполнить свои разделы и строки только после , когда словарь полностью загружен данными моей сети? Я использую обработчик завершения, но когда я пытаюсь распечатать результаты dataDict, он выводит три массива подряд, например так ...

["Monday": ["Chest", "Arms"]]
["Tuesday": ["Back"], "Monday": ["Chest", "Arms"]]
["Tuesday": ["Back"], "Monday": ["Chest", "Arms"], "Wednsday": ["Legs", "Arms"]]

Тогда как я ожидал вернуть один отпечаток массива после завершения. Что я делаю не так?

enter image description here enter image description here

var dataDict : [String:[String]] = [:]


//MARK: - viewDidLoad()
override func viewDidLoad() {
    super.viewDidLoad()

    vcBackgroundImg()
    navConAcc()

    picker.delegate = self
    picker.dataSource = self

    tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellID)
    tableView.tableFooterView = UIView()

    Auth.auth().addStateDidChangeListener { (auth, user) in
        self.userIdRef = user!.uid
        self.colRef = Firestore.firestore().collection("/users/\(self.userIdRef)/Days")

        self.loadData { (done) in
            if done {
                print(self.dataDict)
            } else {
                print("Error retrieving data")
            }
        }

    }

}

//MARK: - Load Data
func loadData(completion: @escaping (Bool) -> ()){
        self.colRef.getDocuments { (snapshot, err) in
            if let err = err
            {
                print("Error getting documents: \(err)");
                completion(false)
            }
            else {
                //Appending all Days collection documents with a field of "dow" to daysarray...
                for dayDocument in snapshot!.documents {
                    self.daysArray.append(dayDocument.data()["dow"] as? String ?? "")
                    self.dayIdArray.append(dayDocument.documentID)


                    Firestore.firestore().collection("/users/\(self.userIdRef)/Days/\(dayDocument.documentID)/Workouts/").getDocuments { (snapshot, err) in
                        if let err = err
                        {
                            print("Error getting documents: \(err)");
                            completion(false)
                        }
                        else {
                            //Assigning all Workouts collection documents belonging to selected \(dayDocument.documentID) to dictionary dataDict...
                            for document in snapshot!.documents {

                                if self.dataDict[dayDocument.data()["dow"] as? String ?? ""] == nil {
                                    self.dataDict[dayDocument.data()["dow"] as? String ?? ""] = [document.data()["workout"] as? String ?? ""]
                                } else {
                                    self.dataDict[dayDocument.data()["dow"] as? String ?? ""]?.append(document.data()["workout"] as? String ?? "")
                                }
                                DispatchQueue.main.async {
                                    self.tableView.reloadData()
                                }
                                // print(self.dataDict)
                            }
                            completion(true)
                        }
                    }
                }
                self.dayCount =  snapshot?.count ?? 0
            }
        }
    }

Ответы [ 2 ]

2 голосов
/ 08 мая 2020

Я согласен с ответом @ ewizard. Проблема в потоке вашей программы. Вы просматриваете документы и выбираете документы в коллекции для каждой итерации. Вы также повторно загружаете tableView и завершение вызова несколько раз, чего не хотите делать.

Чтобы улучшить поток вашей программы, попробуйте использовать DispatchGroup для извлечения ваших данных, а затем собрать их один раз, когда все данные получены. Смотрите пример ниже, чтобы получить основную идею c. Мой пример - очень упрощенная версия вашего кода, в которой я хотел показать вам важные изменения, которые вы должны выполнить.

func loadData(completion: @escaping (Bool) -> ()) {
    self.colRef.getDocuments { (snapshot, err) in
        // Handle error

        let group = DispatchGroup()
        var fetchedData = [Any]()

        // Iterate through the documents
        for dayDocument in snapshot!.documents {
            // Enter group
            group.enter()
            // Fetch data
            Firestore.firestore().collection("/users/\(self.userIdRef)/Days/\(dayDocument.documentID)/Workouts/").getDocuments { (snapshot, err) in
                // Add your data to fetched data here
                fetchedData.append(snapshot)
                // Leave group
                group.leave()
            }
        }

        // Waits for until all data fetches are finished
        group.notify(queue: .main) {
            // Here you can manipulate fetched data and prepare the data source for your table view
            print(fetchedData)

            // Reload table view and call completion only once
            self.tableView.reloadData()
            completion(true)
        }
    }
}

Я также согласен с другими комментариями о том, что вам следует переосмыслить модель данных для вашего tableView. Гораздо более подходящей структурой будет двумерный массив (массив массивов - первый массив преобразуется в разделы табличного представления, а объекты внутреннего массива преобразуются в элементы секций). Вот пример:

// Table view data source
[
    // Section 0
    [day0, day1],
    // Section 1
    [day2, day3],
    // Section 2
    [day4, day5],
]

Пример использования:

extension ViewController: UITableViewDataSource {

    func numberOfSections(in tableView: UITableView) -> Int {
        return sections.count
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return sections[section].count
    }

}
2 голосов
/ 05 мая 2020

Я думаю, что это просто поток вашей программы. Каждый раз, когда вы просматриваете коллекцию, вы добавляете то, что она получает, в словарь. Таким образом, при первом проходе будет напечатано, что в словаре есть 1 элемент. На втором проходе он добавляет еще один элемент в словарь, а затем печатает словарь, в котором теперь есть 2 элемента, поэтому печатаются 2 элемента. Я не думаю, что вы наблюдаете непредвиденное поведение, это просто то, как вы упорядочиваете свой лог-оператор с тем, как вы зацикливаетесь.

Другими словами, имеет смысл, что он печатает именно так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...