如何在 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描述了几种解决问题的方法:
- 创建包含相关数据的(一个)非托管 Realm 对象(该问题仅发生在由领域支持的对象上)。
- 将数据读出到具有线程安全类型(例如字符串、整数等)的变量中
使用新的 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)
我尝试调试并跟踪错误发生在哪一行,我在阅读 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描述了几种解决问题的方法:
- 创建包含相关数据的(一个)非托管 Realm 对象(该问题仅发生在由领域支持的对象上)。
- 将数据读出到具有线程安全类型(例如字符串、整数等)的变量中
使用新的
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)