UI冻结在tableview reloadData()上

时间:2018-09-24 01:39:52

标签: ios swift uitableview realm reloaddata

我有一个简单的词典项目,在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()?

1 个答案:

答案 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