如何解决如何在不崩溃 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()
}
}
这是tableview的代码:
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 否则忽略结果,下一次后续调用仍然会更新结果
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。