在tableView-iOS中处理异步Firestore数据读取
我想从我的简单Firestore数据库中检索数据 我有这个数据库: 然后我有一个模型类,其中有一个方法负责检索数据,如下所示:在tableView-iOS中处理异步Firestore数据读取,ios,swift,firebase,google-cloud-firestore,Ios,Swift,Firebase,Google Cloud Firestore,我想从我的简单Firestore数据库中检索数据 我有这个数据库: 然后我有一个模型类,其中有一个方法负责检索数据,如下所示: func getDataFromDatabase() -> [String] { var notes: [String] = [] collectionRef = Firestore.firestore().collection("Notes") collectionRef.addSnapshotListener { querySnap
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
}
作为UI表示,我有tableViewController。让我们以其中一种方法为例
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("tableview numberOfRowsInSection called")
return model.getDataFromDatabase().count
}
然后numberOfRows为0,控制台中的输出为:
我在tableView中没有单元格。我添加了一个断点,它不会在侦听器中跳转
即使我有三个,他们还是有点“迟到”?然后再装。然后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的方法下面
我还有两个错误(我不知道为什么每行写两次),它们是:
但我认为这与问题无关
谢谢你的帮助 每次检索数据时,只需刷新表单元格即可。在数组中设置数据后,请输入此代码
self.tableView.reloadData()
您只需在每次检索数据时刷新表单元格。在数组中设置数据后,请输入此代码
self.tableView.reloadData()
正如@Galo Torres Sevilla提到的,
addSnapshotListener
方法是异步的,您需要将完成处理程序添加到getDataFromDatabase()
函数中
在代码中进行以下更改:
var list_notes = [String]()
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)
}
}
TableView
,如下所示:
self.getDataFromDatabase { (list_notes) in
self.list_notes = list_notes
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
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
}
正如@Galo Torres Sevilla提到的,
addSnapshotListener
方法是异步的,您需要将完成处理程序添加到getDataFromDatabase()
函数中
在代码中进行以下更改:
var list_notes = [String]()
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)
}
}
TableView
,如下所示:
self.getDataFromDatabase { (list_notes) in
self.list_notes = list_notes
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
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
}
Firestore是异步的,因此notes在从服务器下载数据之前以空数组的形式返回。填充viewController变量并添加一个didSet观察者,或者将completionHandler添加到
getDataFromDatabase
method@GaloTorresSevilla请您提供代码解决方案好吗?至少是一些较小的,因为这是我第一次实现它。我理解你的评论,但我无法实施。谢谢。@MapeSVK我刚刚发布了一个解决方案。希望有帮助@MapeSVK实际上手头没有电脑。这就是为什么我没有发布答案。但是@Bhumik的answerFirestore是异步的,所以notes在从服务器下载数据之前以空数组的形式返回。填充viewController变量并添加一个didSet观察者,或者将completionHandler添加到getDataFromDatabase
method@GaloTorresSevilla请您提供代码解决方案好吗?至少是一些较小的,因为这是我第一次实现它。我理解你的评论,但我无法实施。谢谢。@MapeSVK我刚刚发布了一个解决方案。希望有帮助@MapeSVK实际上手头没有电脑。这就是为什么我没有发布答案。但是你已经有了一个很好的@Bhumik的答案谢谢你,伙计,这很有效!只有一个问题。为什么这么复杂?这不是最基本的东西吗?也许我做得不对,对吧?很高兴这有帮助!代码的唯一问题是,您并没有等待Firestore下载数据。因此,cellForRowAt:indepath:
方法在下载完成之前执行。通过添加完成处理程序,它解决了这个问题。谢谢你,伙计,它工作了!只有一个问题。为什么这么复杂?这不是最基本的东西吗?也许我做得不对,对吧?很高兴这有帮助!代码的唯一问题是,您并没有等待Firestore下载数据。因此,cellForRowAt:indepath:
方法在下载完成之前执行。通过添加完成处理程序,它解决了这个问题。