我有一个简单的词典项目,在Realm模型中有35000多个记录。从这些记录中搜索单词时,键盘敲击看起来有些冻结。我认为用新记录更新表视图时会冻结。
import UIKit
import RealmSwift
class TestTableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate {
@IBOutlet weak var searchBar: UISearchBar!
@IBOutlet weak var tableView: UITableView!
let realm = try! Realm()
var myRealmObject: Results<MyRealmObject>!
override func viewDidLoad() {
super.viewDidLoad()
myRealmObject = realm.objects(MyRealmObject.self).sorted(byKeyPath: "german", ascending: true)
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myRealmObject.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = myRealmObject[indexPath.row].german
return cell
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
myRealmObject = realm.objects(MyRealmObject.self).filter("german beginswith[cd] %@", searchText)
print("Objects count - ", myRealmObject.count)
// self.tableView.performSelector(onMainThread: Selector("reloadData"), with: nil, waitUntilDone: true)
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
如果注释self.tableView.reloadData()并在控制台中打印Realm对象的结果而不会冻结。如何执行tableview.reload Data()?
答案 0 :(得分:0)
您的键盘冻结了,您正在对主线程执行筛选,这需要花费一些时间来操作35000个对象。根据我的理解,您需要将以下行放在后台线程中或使用GCD异步执行它< / p>
myRealmObject = realm.objects(MyRealmObject.self).filter("german beginswith[cd] %@", searchText)
创建串行队列
private let serialQueue =
DispatchQueue(label: "com.example.searchQueue", attributes: .serial)
,然后在您的textDidChange
serialQueue.async { [weak self] in
guard let self = self else {
return
}
// put your filter logic in here
//self.myRealmObject = self.realm.objects(MyRealmObject.self).filter("german beginswith[cd] %@", searchText)
DispatchQueue.main.sync { [weak self] in
self?.tableView.reloadData()
}
}
但是,您还需要考虑其他事项。当用户快速输入时,值得考虑在开始新任务之前取消先前的任务,或者可能使用asyncAfter