I am trying to do searching in the table view, with the throttle.
Here I have BehaviorRelay in ViewModel
var countryCodes: BehaviorRelay<[CountryDialElement]> = BehaviorRelay<[CountryDialElement]>(value:[])
Here I have BehaviorRelay for the entered text
var searchText: BehaviorRelay<String> = BehaviorRelay<String>(value: "")
Here I have Table View which is binded with Observable from View Model
self.viewModel.params.countryCodes.bind(to: tableView.rx.items(cellIdentifier: "CountryDialTableViewCell")) { index, model, cell in
let countryCell = cell as! CountryDialTableViewCell
countryCell.configure(model)
}.disposed(by: disposeBag)
Here I have Rx binding to UISearchBar in ViewController
searchBar
.rx
.text
.orEmpty
.debounce(.milliseconds(300), scheduler: MainScheduler.instance)
.distinctUntilChanged()
.subscribe { [weak self] query in
guard
let query = query.element else { return }
self?.viewModel.params.searchText.accept(query)
}
.disposed(by: disposeBag)
Then in ViewModel, I am trying to filter data and push filtered data to dataSource, to update the tableView.
Observable.combineLatest(params.countryCodes, params.searchText) { items, query in
return items.filter({ item in
item.name.lowercased().contains(query.lowercased()) || item.dialCode.lowercased().contains(query.lowercased())
})
}.subscribe(onNext: { resultArray in
self.params.countryCodes.accept(resultArray)
})
.disposed(by: disposeBag)
But I am getting this type of Error
Reentrancy anomaly was detected.
This behavior breaks the grammar because there is overlapping between sequence events.
The observable sequence is trying to send an event before sending the previous event has finished.
Interpretation: This could mean that there is some kind of unexpected cyclic dependency in your code, or that the system is not behaving in an expected way.
I am trying to achieve:
First thing I noticed... You have two BehaviorRelays defined as var
. You should always define them with let
.
You haven't posted enough code to demonstrate the error but the fundamental problem, as explained to you in the error message, is that you are breaking the observable grammar because you are pushing data through an Observable while in the middle of pushing data. If allowed, it would form an infinite recursive call that would overflow the stack.
Don't send an event until after the current event is finished sending. It would help a lot if you didn't use so many Relays...
You don't say anything about where the items in the array come from which also makes it hard to help...
Consider something like this:
Observable.combineLatest(
searchBar.rx.text.orEmpty
.debounce(.milliseconds(300), scheduler: MainScheduler.instance)
.distinctUntilChanged()
.startWith(""),
sourceOfItems(),
resultSelector: { searchTerm, items in
items.filter { $0.code.contains(searchTerm) }
}
)
.bind(to: tableView.rx.items(cellIdentifier: "CountryDialTableViewCell")) { index, model, cell in
let countryCell = cell as! CountryDialTableViewCell
countryCell.configure(model)
}
.disposed(by: disposeBag)