【问题标题】:TableView data from search not updated properly来自搜索的 TableView 数据未正确更新
【发布时间】:2019-01-28 21:26:46
【问题描述】:

我使用 Swift 制作了一个 TableView,其中显示了 UiTextField 中填充的查询的搜索结果。

let cellReuseIdentifier = "cell"

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell:SearchCell = self.tableView.dequeueReusableCell(withIdentifier:cellReuseIdentifier) as! SearchCell
    cell.objectName.text = self.search_results_list[indexPath.section]
    return cell
}

Value Changed 事件中,我触发了 Search 操作:

 @IBAction func searchInputChanged(_ sender: Any) {
    self.search_results_list = []
    let search = self.searchField.text
    let parameters: Parameters = ["api_token": token, "search": search!+" "]
    let URL = "https://myweb.app/api/search"
    Alamofire.request(URL, parameters: parameters).responseArray { (response: DataResponse<[SearchResponse]>) in
        let searchResultsArray = response.result.value
        if let searchResultsArray = searchResultsArray {
            for searchResult in searchResultsArray {
                self.search_results_list.append(searchResult.description!)
            }
        }
        // Then I reloeadData of the TableView
        self.tableView.reloadData()
    }
}

还有 NumberOfSections 方法:

func numberOfSections(in tableView: UITableView) -> Int {
        return self.search_results_list.count
    }
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }

确实有效,但是当我快速填写表格时,Array 的顺序正确,但 TableView 的顺序不同。当我检查数组时,我发现顺序是正确的,但 TableView 显示的是不同的。当我等待一秒钟并在最后添加一个空格时,TableView 确实显示了正确的顺序。 当我逐个字母添加并在每个字母后等待重新加载 tableview 时也是如此,输出是正确的

我错过了什么?

【问题讨论】:

  • 一个潜在的问题是,如果您快速点击“ab”,您将搜索“a”,然后搜索“b”。但是由于调用是异步的,您的服务器可能会快速响应“ab”,然后响应“a”,因此您的结果是错误的,因为它仅适用于“a”,而您当前的文本是“ab”。
  • @Larme 我检查了服务器并且输入正确发送,它显示了正确的值。但实际上,看起来已经给出了一个新的输出,但还没有被 Swift 渲染或其他东西
  • @AshleyMills 根本没用
  • 这需要一个堆栈,将请求添加到 ,如果不是来自最顶部的项,则忽略响应
  • @Sh_Khan 我不明白你的意思,你能简单解释一下吗?谢谢

标签: ios swift uitableview alamofire


【解决方案1】:

就像他们在 cmets 中所说的那样。这可能是因为异步调用在不同时间返回。并且很可能结果较少(较新的调用)的返回更快比具有更多结果(较旧的调用)的返回。因此,您需要做的是使每个 API 响应不匹配您的当前搜索文本

@IBAction func searchInputChanged(_ sender: Any) {
    self.search_results_list = []
    let search = self.searchField.text
    let parameters: Parameters = ["api_token": token, "search": search!+" "]
    let URL = "https://myweb.app/api/search"
    Alamofire.request(URL, parameters: parameters).responseArray { (response: DataResponse<[SearchResponse]>) in
        if search == self.searchTextField.text {             // Compare search text with current text in searchTextField.
            let searchResultsArray = response.result.value
            if let searchResultsArray = searchResultsArray {
                for searchResult in searchResultsArray {
                    self.search_results_list.append(searchResult.description!)
                }
            }
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }
        }
    }
}

重要的优化提示

您可以将 API 调用包装在 计时器 中,以便仅当用户停止在文本字段中输入字符时才会触发它。这有助于避免不必要的 API 调用。您可以通过使用Timer 进行网络调用来实现此目的。在textDidChange 中启动计时器,如果在短时间内(0.5 秒或任何您认为最佳的时间)再次调用委托,则使其无效

【讨论】:

  • WAUW,看起来这个简单的解决方案就是解决方案!谢谢:)
  • 感谢您的提示;也解决了这个问题:) @rakesha-shastri
  • 为什么是“DispatchQueue”?只是好奇这是做什么的,因为没有它也可以工作
  • @user1469734 API 调用在后台线程上运行,如果您在其闭包内调用 UI 操作(仍将在后台线程中),它们将无法正常运行。 UI 调用应始终在主线程上调用。
猜你喜欢
  • 2020-07-22
  • 1970-01-01
  • 2014-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-23
  • 1970-01-01
相关资源
最近更新 更多