【问题标题】:SearchBar problem while trying to search Firestore and reload the tableview尝试搜索 Firestore 并重新加载 tableview 时出现 SearchBar 问题
【发布时间】:2019-06-04 10:57:20
【问题描述】:

我有一个 tableView,我使用无限滚动来批量填充 firestore 数据。另外我有一个搜索栏,我正在尝试使用文本栏中的文本查询 firestore,然后将其填充到 tableview 中。我有 3 个主要问题。

  1. 当我第一次单击搜索时,我得到一个空数组和一个空的 tableview,但是当我第二次单击搜索时,一切似乎都很好。

  2. 当我最终填充搜索到的内容时,我希望在滚动时停止获取新内容。

  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() 因为它工作正常,我认为不相关。 提前致谢。

【问题讨论】:

    标签: swift firebase uitableview google-cloud-firestore uisearchbar


    【解决方案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 时,滚动后分页再次开始。无法禁用滚动,因为数据可能超过屏幕高度。
    猜你喜欢
    • 2017-08-30
    • 1970-01-01
    • 1970-01-01
    • 2011-06-20
    • 1970-01-01
    • 2020-01-16
    • 2019-09-14
    • 1970-01-01
    • 2022-06-23
    相关资源
    最近更新 更多