ios - UI 在 tableview reloadData() 上卡住

标签 ios swift uitableview realm reloaddata

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

最佳答案

你的键盘卡住了,因为你正在主线程上执行过滤器,这需要时间来操作 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

关于ios - UI 在 tableview reloadData() 上卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52471760/

相关文章:

ios - 用 2 个 block 排队 GCD

ios - 在当前 View Controller 具有 UITabBar 但没有 UITabBarController 时呈现 View Controller

ios - 我是否需要包含整个 SDWebImage 库以在 UICollectionView 中下载图像?

iphone - 使用 CGLayer 缓存 UITableView 中的单元格

ios - 核心数据关系(快速)

objective-c - 尝试添加行时应用程序不断崩溃?

swift - 在 Swift 中为 Apple Watch 制作一个简单的淡入淡出动画?

ios - 如何在 Swift 中将图像转换为渐进式 JPEG?

ios - 为什么页眉和页脚在删除时会跟随行的移动?

ios - 基本从 Firebase 读取并用结果加载 TableView (Swift)