swift - 如何在不破坏 UI 的情况下将搜索放在另一个线程中?
问题描述
我有一个搜索栏和一个显示结果的表格视图。我有一个包含 150.000 种食物的数据(这是一个非常大的数据)所以当用户点击字母时,UI 会阻止每个字母,并花时间搜索数据并显示结果。问题不在于花时间显示结果。问题是在点击每个字母后键盘会阻塞,等待 tableview 显示结果。这不是一个好的用户体验。
以下是搜索栏的部分代码:
extension AjoutAlimentController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
let words = Set(searchText.split(separator: " ").map(String.init))
if searchText.isEmpty {
baseDeDonneesAlimentsFiltree = [] //baseOuChercheAliments
} else {
var baseDeDonneesAlimentsFiltreeClassique = baseOuChercheAliments.filter{$0.nomAliment.range(of: searchText, options: .anchored) != nil}
baseDeDonneesAlimentsFiltreeClassique.sort(by: { $0.indice > $1.indice})
var baseDeDonneesAlimentsFiltreeComplexe = baseOuChercheAliments.filter { object in words.allSatisfy { word in object.nomAliment.localizedCaseInsensitiveContains(word) } }
baseDeDonneesAlimentsFiltreeComplexe.sort(by: { $0.indice > $1.indice })
var soustraction = Array(Set(baseDeDonneesAlimentsFiltreeComplexe).subtracting(baseDeDonneesAlimentsFiltreeClassique))
soustraction.sort(by: { $0.indice > $1.indice })
baseDeDonneesAlimentsFiltree = baseDeDonneesAlimentsFiltreeClassique + soustraction
}
self.tableView.reloadData()
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchBar.resignFirstResponder()
}
}
这是表格视图的代码:
extension AjoutAlimentController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if baseDeDonneesAlimentsFiltree.count >= 500 {
return 500
} else { return baseDeDonneesAlimentsFiltree.count }
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "AlimentToAddCell", for: indexPath) as? AlimentToAddCell else {
return UITableViewCell() }
let alimentFind = baseDeDonneesAlimentsFiltree[indexPath.row] // Here is where the crash occures when i put the search in another thread
cell.indice.text = String(alimentFind.indice.formattedWithSeparator)
cell.selectionStyle = .none
return cell
}
有没有办法在用户点击每个字母后将搜索放入一个线程而不会使应用程序崩溃?所以 UI 会以它的节奏显示结果,并且键盘不会阻塞。
解决方案
您始终可以将耗时的任务委托给全局队列(非 ui 线程),一旦数据完成,您始终可以切换到主线程并调用reloadData
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
DispatchQueue.global(qos: .default).async {
let searchTextBeingQuireid = searchText
var searchedRecords = [AlimentObject]() //not sure type of your array, mention appropriate type here
let words = Set(searchText.split(separator: " ").map(String.init))
if searchText.isEmpty {
searchedRecords = [] //baseOuChercheAliments
} else {
var baseDeDonneesAlimentsFiltreeClassique = baseOuChercheAliments.filter{$0.nomAliment.range(of: searchText, options: .anchored) != nil}
baseDeDonneesAlimentsFiltreeClassique.sort(by: { $0.indice > $1.indice})
var baseDeDonneesAlimentsFiltreeComplexe = baseOuChercheAliments.filter { object in words.allSatisfy { word in object.nomAliment.localizedCaseInsensitiveContains(word) } }
baseDeDonneesAlimentsFiltreeComplexe.sort(by: { $0.indice > $1.indice })
var soustraction = Array(Set(baseDeDonneesAlimentsFiltreeComplexe).subtracting(baseDeDonneesAlimentsFiltreeClassique))
soustraction.sort(by: { $0.indice > $1.indice })
searchedRecords = baseDeDonneesAlimentsFiltreeClassique + soustraction
}
if searchText == searchTextBeingQuireid {
DispatchQueue.main.async {
baseDeDonneesAlimentsFiltree = searchedRecords
self.tableView.reloadData()
}
}
}
}
您可以进行一些优化:
通常,每当我们进行连续搜索调用,并且数据在我们将其显示在屏幕上之前异步返回时,我们会检查响应本身的有效性,假设用户类型App
您使用搜索文本进行调用以搜索您的数据库,App
并且在数据返回之前用户添加 l 制作文本Appl
,然后显示只有App
n 没有的数据Appl
看起来像一个错误,因此我添加了 2 个新变量searchTextBeingQuireid
,searchedRecords
一旦您完成搜索,通过检查是否仍然有效来检查您的数据是否仍然searchTextBeingQuireid
有效searchText
或不是。如果是通过调用更新您的数据源baseDeDonneesAlimentsFiltree = searchedRecords
,最后调用reloadData
更新 tableView 否则忽略结果,下一次后续调用将更新结果
推荐阅读
- android - 如何在 recylerview 中为具有单个适配器的多个模型类实现多视图类型?
- javascript - .GetElementsByName.SelectedIndex 明显改变选项但不是以编程方式?
- python - 使用 matplotlib 库绘制列表(不按顺序)时如何更正 y 间隔?
- python - scipy.stats 导入 describe() 时出现问题
- mt4 - 如何与 Metatrader 4 服务器通信以从中读取数据?
- java - 如何使用货币掩码 EditText 构建 ListView
- html - 打印时如何更改div的宽度?
- typo3 - 当 TYPO3 9LTS 中的参数“slugified”时,GPVar 条件不起作用
- excel - 如何让我的 VBA 网页抓取代码跟上新窗口的速度?
- coldfusion - 将可选参数传递给远程访问的 CFC 的策略