【问题标题】:UI freezes on tableview reloadData()UI 在 tableview reloadData() 上冻结
【发布时间】:2018-09-24 01:39:52
【问题描述】:

我有一个简单的字典项目,在 Realm 模型中有超过 35000 条记录。当从这些记录中搜索单词时,键盘敲击看起来有点冻结。我认为当我用新记录更新我的 tableview 时会冻结。

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() ?

【问题讨论】:

  • 您的IBOutlet 连接了吗? “冻结”是什么意思?该应用程序因异常而停止?控制台说什么?
  • 一方面,当你已经在主线程上时调用 DispatchQueue.main.async 是没有意义的,而且会搞砸工作。
  • @Alejandro Iván IBOutlet 已连接。当点击键盘搜索 0.2-0.6 秒冻结键盘然后更新 tableview
  • @matt 没有 DispatchQueue.main.async 问题是相关的。您对执行 tableview.reloadData 有什么建议吗?
  • @matt DispatchQueue.main.async 不是异步获取主队列吗?

标签: ios swift uitableview realm reloaddata


【解决方案1】:

您的键盘正在冻结,因为您正在主线程上执行过滤器,这需要时间来操作 35000 个对象。根据我的理解,您需要将以下行放在后台线程中或使用 GCD 异步执行它

 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

【讨论】:

  • 感谢您的回答。但是,根据您的建议继续冻结键盘。我稍微修改一下你的代码:
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-22
相关资源
最近更新 更多