如何解决此问题Terminating app due to uncaught exception 'RLMException', reason: 'Realm accessed from incorrect thread.'
,我花了两天时间寻找此问题的解决方案。我希望有人可以帮助我。我尝试调试并跟踪它,我发现它成功进入.subscribe(onNext:)
并读取controller?.tableView.reloadData()
但是如果我继续执行程序,它将终止并在控制台日志中显示错误。
searchBar
.rx.text
.orEmpty
.debounce(0.5, scheduler: MainScheduler.instance)
.distinctUntilChanged()
.filter { !$0.isEmpty }
.map({ [weak controller = self] query -> (tcb: [TrialCourtBranches], query: String)? in
switch controller?.tcbArray {
case .some(let array):
return (array, query)
case .none:
return nil
}
})
.observeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated)) // change thread before filtering
.map({ (query) -> [TrialCourtBranches] in // filter and return the result of filtering
let realm = try! Realm()
let tcb = realm.objects(TrialCourtBranches.self)
let tcb_safe = ThreadSafeReference(to: tcb)
let filtered = realm.resolve(tcb_safe)
let tcb_filtered:[TrialCourtBranches] = (filtered?.filter({ $0.branch_name.lowercased().contains(searchText.lowercased()) }))!
return tcb_filtered
})
.observeOn(MainScheduler.instance) // go back to main thread
.subscribe(onNext: { [weak controller = self] (filtered) in
tcb_filteredArray = filtered
controller?.tableView.reloadData()
})
.disposed(by: bag)
答案 0 :(得分:0)
Please note I'm not really an IOS dev so this code could easily end up syntactically incorrect, but the issue is that this just isn't a good way to filter in Realm.
You could for example use RxRealm from https://github.com/RxSwiftCommunity/RxRealm which allows you to expose Results as a Changeset Observable.
Then you can switchMap (or in your language, flatMapLatest) on it.
So the end result would be something like this
extension UITableView {
func applyChangeset(_ changes: RealmChangeset) {
beginUpdates()
deleteRows(at: changes.deleted.map { IndexPath(row: $0, section: 0) }, with: .automatic)
insertRows(at: changes.inserted.map { IndexPath(row: $0, section: 0) }, with: .automatic)
reloadRows(at: changes.updated.map { IndexPath(row: $0, section: 0) }, with: .automatic)
endUpdates()
}
}
And
searchBar
.rx.text
.orEmpty
.debounce(0.5, scheduler: MainScheduler.instance)
.distinctUntilChanged()
.filter { !$0.isEmpty }
.map({ [weak controller = self] query -> (tcb: [TrialCourtBranches], query: String)? in
switch controller?.tcbArray {
case .some(let array):
return (array, query)
case .none:
return nil
}
})
.flatMapLatest({ (query) -> [TrialCourtBranches] in // filter and return the result of filtering
let realm = try! Realm()
let results = realm.objects(TrialCourtBranches.self)
.filtered($0.branch_name.lowercased()
.contains(searchText.lowercased()))
return Observable.changeset(from: results)
})
.subscribe(onNext: {[unowned self] results, changes in
if let changes = changes {
controller?.tableView.applyChangeset(changes)
} else {
controller?.tableView.reloadData()
}
})
.disposed(by: bag)
答案 1 :(得分:0)
正确输出
[HttpGet]
public async Task<IStore> GetStore(int id)
{
IStore result = await ShopExpressions.Store(GenericExpressions.ClientAccess(this.Worker.GetRepo<Store>().DbSet))
.SingleAsync(str => str.Id.Equals(id));
this.Worker.ValidateClientAccess(result);
return result;
}
[HttpGet]
public async Task<IStore> GetStoreLite(int id)
{
IStore result = await ShopExpressions.StoreLite(GenericExpressions.ClientAccess(this.Worker.GetRepo<Store>().DbSet))
.SingleAsync(str => str.Id.Equals(id));
this.Worker.ValidateClientAccess(result);
return result;
}
[HttpGet]
public async Task<IPage> GetPage(int id)
{
IPage result = await ShopExpressions.Page(this.Worker.GetRepo<Page>().DbSet)
.SingleAsync(page => page.Id.Equals(id));
return result;
}