如何在 swift 4 中解决此问题“从不正确的线程访问领域”。

How to fix this issue `Realm accessed from incorrect thread.` in swift 4

我尝试调试并跟踪错误发生在哪一行,我在阅读 print(tcb_filteredArray) 后发现错误发生,我尝试将 print(tcb_filteredArray) 放在 self.tableView.reloadData() 下方并进行调试并再次跟踪它,它仍然在 print(tcb_filteredArray)

中发生错误

我的搜索过滤代码

        let realm = try! Realm()
        let tcb = realm.objects(TrialCourtBranches.self)
        let tcb_safe = ThreadSafeReference(to: tcb)
        DispatchQueue.global(qos: .userInitiated).sync {
            guard let filtered = realm.resolve(tcb_safe) else{ return }
            tcb_filteredArray = filtered.filter({ [=11=].branch_name.lowercased().contains(searchText.lowercased()) || ([=11=].loc?.pc?.province.lowercased().contains(searchText.lowercased()))! || ([=11=].loc?.pc?.city_municipality.lowercased().contains(searchText.lowercased()))! || [=11=].office_no.lowercased().contains(searchText.lowercased())})
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }
        }

默认情况下,Realm 对象只能从创建它们的线程访问。因此,在后台线程上创建的过滤对象数组无法在主线程上直接访问。

Realm 对此提供了几个解决方案 - 有关详细信息,请参阅 this blog post

post描述了几种解决问题的方法:

  1. 创建包含相关数据的(一个)非托管 Realm 对象(该问题仅发生在由领域支持的对象上)。
  2. 将数据读出到具有线程安全类型(例如字符串、整数等)的变量中
  3. 使用新的 ThreadSafeReference class - 执行以下步骤:

    • 在原帖中创建引用:
      let personRef = ThreadSafeReference(to: person)

      (其中 person 是一个 Realm 支持的对象)

    • 在第二个线程块中,解析引用:

       let realm = try! Realm()
       guard let person = realm.resolve(personRef) else {
         return // person was deleted
       } 
      

如果您沿着这条路走,您需要将数组中的每个项目包装在 ThreadSafeReference 中。

这是正确答案

searchBar.rx.text.orEmpty.debounce(0.3, scheduler: MainScheduler.instance)
        .distinctUntilChanged()
        .filter { ![=10=].isEmpty }
        .observeOn(MainScheduler.instance)
            .subscribe(onNext: { (data) in
                let realm = try! Realm()
                let tcb = realm.objects(TrialCourtBranches.self)
                let predicate = NSPredicate(format: "(branch_name CONTAINS[c] %@) OR (office_no CONTAINS[c] %@) OR (loc.pc.city_municipality CONTAINS[c] %@) OR (loc.pc.province CONTAINS[c] %@) OR (loc.address1 CONTAINS[c] %@)",data.lowercased(),data.lowercased(),data.lowercased(),data.lowercased(),data.lowercased())
                tcb_filteredArray = tcb.filter(predicate)
                self.tableView.reloadData()
            }, onError: { (errorResult) in
                print(errorResult)
            }, onCompleted: {
                print("onCompleted")
            }, onDisposed: {
                print("onDisposed")
            })
        .disposed(by: bag)