尝试搜索 Firestore 并重新加载 tableview 时出现 SearchBar 问题
Posted
技术标签:
【中文标题】尝试搜索 Firestore 并重新加载 tableview 时出现 SearchBar 问题【英文标题】:SearchBar problem while trying to search Firestore and reload the tableview 【发布时间】:2019-06-04 10:57:20 【问题描述】:我有一个 tableView,我使用无限滚动来批量填充 firestore 数据。另外我有一个搜索栏,我正在尝试使用文本栏中的文本查询 firestore,然后将其填充到 tableview 中。我有 3 个主要问题。
当我第一次单击搜索时,我得到一个空数组和一个空的 tableview,但是当我第二次单击搜索时,一切似乎都很好。
当我最终填充搜索到的内容时,我希望在滚动时停止获取新内容。
如果我输入了错误的单词并按了搜索,那么我会得到上一个搜索结果,然后“未找到任何成分”会打印两次。
这是我的 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() 因为它工作正常,我认为不相关。 提前致谢。
【问题讨论】:
【参考方案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。
您还可以在填充数组之前返回它。更重要的是,通常可以(并且应该)避免尝试从异步函数返回值。
解决方法是处理闭包内的数据
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 函数不应返回值 - 也不需要
【讨论】:
感谢您的回答。你让我明白了很多,它奏效了。现在的问题是它打印了两次“未找到成分”。 @NickStefanidis 好吧,有可能函数被调用了两次,或者 print 语句可能在循环中。该功能适用于我,只打印一次。也许用更新的代码和 Firestore 结构的 sn-p 询问另一个问题会有所帮助。 谢谢。这是我的错误。还有一件事。我有无限卷轴。当我拥有已建立的单元格时是否可以停止获取?会有超过 1 个,因为我有同义词。 @NickStefanidis 通常,如果您想要无限滚动,您将对数据进行分页,例如,您的应用程序一次加载 10 行,然后当用户滚动时,它将加载下一个 10等等。Paginating Data上的 Firestore 指南中有一些很棒的信息 我成功地对我的数据进行了分页,这不是问题。但是,当我搜索某些内容并使用已找到的数据重新加载 tableView 时,滚动后分页再次开始。无法禁用滚动,因为数据可能超过屏幕高度。以上是关于尝试搜索 Firestore 并重新加载 tableview 时出现 SearchBar 问题的主要内容,如果未能解决你的问题,请参考以下文章
如何在不重新加载页面的情况下更新从 firestore 检索到的标记在我的地图上?