Обработка асинхронного чтения данных Firestore в tableView - iOS - PullRequest
0 голосов
/ 04 апреля 2019

Я хотел бы получить данные из моей простой базы данных Firestore

У меня есть эта база данных: enter image description here

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

func getDataFromDatabase() -> [String] {
    var notes: [String] = []
    collectionRef = Firestore.firestore().collection("Notes")

    collectionRef.addSnapshotListener { querySnapshot, error in
            guard let documents = querySnapshot?.documents else {
                print("Error fetching documents: \(error!)")
                return
            }
        notes = documents.map { $0["text"]! } as! [String] // text is a field saved in document
            print("inside notes: \(notes)")
    }
    print("outside notes: \(notes)")
    return notes
}

и в качестве представления пользовательского интерфейса у меня есть tableViewController.Давайте возьмем один из методов, например

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    print("tableview numberOfRowsInSection called")
    return model.getDataFromDatabase().count
}

Тогда numberOfRows равно 0 и вывод в консоли: enter image description here

и я заканчиваюбез ячеек в tableView.Я добавил точку останова, и она не прыгает внутри слушателя.

И хотя у меня их 3, они вроде как "опаздывают"?Они загружаются потом.И тогда tableView ничего не показывает, но консоль говорит (позже), что есть 3 ячейки.

При необходимости, есть также мой метод для отображения имен ячеек:

 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    print("Cells")
    let cell = tableView.dequeueReusableCell(withIdentifier: "firstCell", for: indexPath)

    cell.textLabel!.text = String(model.getDataFromDatabase()[indexPath.row].prefix(30))

    return cell
}

но этот метод даже не загружен (нет печати в консоли), и этот метод записан ниже метода с numberOfRowsInSection.

У меня также есть 2 ошибки (я не знаю, почему каждая строка пишется дважды): enter image description here

, но я не думаю, что этоимеет отношение к проблеме.

Спасибо за вашу помощь!

Ответы [ 2 ]

1 голос
/ 04 апреля 2019

Как уже упоминалось @Galo Torres Sevilla, метод addSnapshotListener является асинхронным, и вам необходимо добавить обработчик завершения в вашу функцию getDataFromDatabase().

Внести следующие изменения в код:

  1. Объявление глобальной переменной для заметок.

    var list_notes = [String]()
    
  2. Добавление обработчика завершения в метод getDataFromDatabase().

    func getDataFromDatabase(callback: @escaping([String]) -> Void) {
        var notes: [String] = []
        collectionRef = Firestore.firestore().collection("Notes")
    
        collectionRef.addSnapshotListener { querySnapshot, error in
            guard let documents = querySnapshot?.documents else {
                print("Error fetching documents: \(error!)")
                return
            }
            notes = documents.map { $0["text"]! } as! [String] // text is a field saved in document
            print("inside notes: \(notes)")
    
            callback(notes)
        }
    }
    
  3. Наконец, вызовите функцию в соответствующем месте, где вы хотите получить заметки и назначить извлеченные заметки для вашей глобальной переменной и перезагрузить TableView, как показано ниже:

    self.getDataFromDatabase { (list_notes) in
        self.list_notes = list_notes
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }
    }
    

Изменения в TableView:

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    print("tableview numberOfRowsInSection called")
    return self.list_notes.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    print("Cells")
    let cell = tableView.dequeueReusableCell(withIdentifier: "firstCell", for: indexPath)

    cell.textLabel!.text = String(self.list_notes[indexPath.row].prefix(30))

    return cell
}
0 голосов
/ 04 апреля 2019

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

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