我有一个tableView,并且使用无限滚动来批量填充Firestore数据。我也有一个搜索栏,我试图用文本栏中的文本查询firestore,然后将其填充到tableview中。我有3个主要问题。
第一次单击搜索时,我得到一个空数组和一个空的表视图,但是第二次单击搜索时,一切似乎都很好。
当我最终填充搜索到的内容时,我想在滚动时停止获取新内容。
如果我输入了错误的单词并按搜索,则会得到上一次搜索,然后打印两次“未找到成分”。
这是我的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()导致其正常工作,我认为这并不相关。 预先感谢。
答案 0 :(得分:1)
您的问题是Firestore是asynchronous。
Firestore需要花费一些时间来返回您所请求的文档,并且该数据仅在调用该函数的闭包内有效。闭包外的代码将在闭包内的数据可用之前执行。
这就是正在发生的事情。
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。
您还将在填充其之前返回IngredientsArray。更重要的是,通常可以避免并且应该避免尝试从异步函数返回值。
解决方法是处理闭包内的数据
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函数不应返回值-也不需要