Reputation: 805
I have a BehaviorSubject
where my tableview is bound to through RxDataSources.
Besides that, I have a pull to refresh which creates an observable that updates the data and updates the data in the BehaviorSubject
so that my UITableView updates correctly.
Now the question is, how do I handle the error handling for whenever my API call fails?
Few options that I have thought of was:
onError
and call the onError
of my BehaviorSubject
\concat
? or bind(to: ..)
ViewController
subscribe besides that my tableview subscribes to the BehaviorSubject
. Any suggestions?
Upvotes: 2
Views: 1098
Reputation: 33967
Ideally, you wouldn't use the BehaviorSubject at all. From the Intro to Rx book:
The usage of subjects should largely remain in the realms of samples and testing. Subjects are a great way to get started with Rx. They reduce the learning curve for new developers, however they pose several concerns...
Better would be to do something like this in your viewDidLoad (or a function that is called from your viewDidLoad):
let earthquakeData = Observable.merge(
tableView.refreshControl!.rx.controlEvent(.valueChanged).asObservable(),
rx.methodInvoked(#selector(UIViewController.viewDidAppear(_:))).map { _ in }
)
.map { earthquakeSummary /* generate URLRequest */ }
.flatMapLatest { request in
URLSession.shared.rx.data(request: request)
.materialize()
}
.share(replay: 1)
earthquakeData
.compactMap { $0.element }
.map { Earthquake.earthquakes(from: $0) }
.map { $0.map { EarthquakeCellDisplay(earthquake: $0) } }
.bind(to: tableView.rx.items(cellIdentifier: "Cell", cellType: EarthquakeTableViewCell.self)) { _, element, cell in
cell.placeLabel.text = element.place
cell.dateLabel.text = element.date
cell.magnitudeLabel.text = element.magnitude
cell.magnitudeImageView.image = element.imageName.isEmpty ? UIImage() : UIImage(named: element.imageName)
}
.disposed(by: disposeBag)
earthquakeData
.compactMap { $0.error }
.map { (title: "Error", message: $0.localizedDescription) }
.bind { [weak self] title, message in
self?.presentAlert(title: title, message: message, animated: true)
}
.disposed(by: disposeBag)
The materialize()
operator turns a Event.error(Error)
result into an Event.next(.error(Error))
so that the chain won't be broken down. The .compactMap { $0.element }
emits only the successful results while the .compactMap { $0.error }
emits only the errors.
The above code is adapted from my RxEarthquake sample.
Upvotes: 3