问题描述
我有一个tableView,并且使用无限滚动以批处理填充Firestore数据.我也有一个搜索栏,我试图用文本栏中的文本查询firestore,然后将其填充到tableview中.我有3个主要问题.
I have a tableView and I use infinite scroll to populate firestore data with batches. Also I have a searched bar and I am trying to query firestore with the text from the text bar and then populate it in the tableview. I have 3 main problems.
-
当我第一次单击搜索时,我得到一个空数组和一个空的表视图,但是当我第二次单击搜索时,一切似乎都很好.
When I click search thee first time I get an empty array and an empty tableview, but when I click search the second time everything seems fine.
当我最终填充搜索到的内容时,我想在滚动时停止获取新内容.
When I finally populate the searched content I want to stop fetching new content while I am scrolling.
如果我输入了错误的单词并按搜索,则得到上一个搜索,然后两次打印找不到成分".
If I text a wrong word and press search then I get the previous search and then the "No Ingredients found" printed twice.
这是我的searchBar代码:
This is my code for searchBar:
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
guard let text = searchBar.text else {return}
searchIngredients(text: text)
self.searchBarIngredient.endEditing(true)
print("\(searchIngredients(text: text))")
}
点击搜索时的功能代码
func searchIngredients(text: String) -> Array<Any>{
let db = Firestore.firestore()
db.collection("Ingredients").whereField("compName", arrayContains: text).getDocuments{ (querySnapshot, err) in
if let err = err {
print("\(err.localizedDescription)")
print("Test Error")
} else {
if (querySnapshot!.isEmpty == false){
self.searchedIngredientsArray = querySnapshot!.documents.compactMap({Ingredients(dictionary: $0.data())})
}else{
print("No Ingredients found")
}
}
}
self.tableView.reloadData()
ingredientsArray = searchedIngredientsArray
return ingredientsArray
}
最后是滚动代码
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let off = scrollView.contentOffset.y
let off1 = scrollView.contentSize.height
if off > off1 - scrollView.frame.height * leadingScreensForBatching{
if !fetchMoreIngredients && !reachEnd{
beginBatchFetch()
}
}
}
我没有编写beginBatchFetch()导致其正常工作,并且我认为不相关.预先感谢.
I don't write the beginBatchFetch() cause its working fine and I don't think is relevant.Thanks in advance.
推荐答案
问题中的问题是Firestore为.
The issue in your question is that Firestore is asynchronous.
Firestore需要花费一些时间来返回您所请求的文档,并且该数据仅在调用该函数的闭包内有效.闭包外的代码将在闭包内的数据可用之前执行.
It takes time for Firestore to return documents you've requested and that data will only be valid within the closure calling the function. The code outside the closure will execute way before the data is available within the closure.
这就是正在发生的事情.
So here's what's going on.
func searchIngredients(text: String) -> Array<Any>{
let db = Firestore.firestore()
db.collection("Ingredients").whereField("compName", arrayContains: text).getDocuments{ (querySnapshot, err) in
//the data has returned from firebase and is valid
}
//the code below here will execute *before* the code in the above closure
self.tableView.reloadData()
ingredientsArray = searchedIngredientsArray
return ingredientsArray
}
正在发生的事情是在数组中没有任何数据之前刷新tableView.
what's happening is the tableView is being refreshed before there's any data in the array.
您还将在填充其之前返回IngredientsArray.更重要的是,通常可以避免并且应该避免尝试从异步函数返回值.
You're also returning the ingredientsArray before it's populated. More importantly, attempting to return a value from an asynchronous function can (and should) generally be avoided.
解决方法是处理闭包内的数据
The fix is to handle the data within the closure
class ViewController: NSViewController {
var ingredientArray = [String]()
func searchIngredients(text: String) {
let db = Firestore.firestore()
db.collection("Ingredients").whereField("compName", arrayContains: text).getDocuments{ (querySnapshot, err) in
//the data has returned from firebase and is valid
//populate the class var array with data from firebase
// self.ingredientArray.append(some string)
//refresh the tableview
}
}
请注意,searchIngredients函数不应返回值-也不需要
Note that the searchIngredients function should not return a value - nor does it need to
这篇关于尝试搜索Firestore并重新加载tableview时出现SearchBar问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!