RxSwift 使 Observable 触发一个主题

RxSwift Make Observable trigger a subject

我有一个 BehaviorSubject,其中我的 tableview 通过 RxDataSources 绑定。

除此之外,我有一个 pull to refresh,它创建一个 observable 来更新数据并更新 BehaviorSubject 中的数据,以便我的 UITableView 正确更新。

现在的问题是,每当我的 API 调用失败时,我该如何处理错误处理?

我想到的几个选项是:

  1. 订阅观察者的onError,调用我的BehaviorSubject\
  2. onError
  3. 想办法concat?或 bind(to: ..)
  4. 除了我的 tableview 订阅 BehaviorSubject 之外,让我的 ViewController 中的另一个订阅者订阅。

有什么建议吗?

理想情况下,您根本不会使用 BehaviorSubject。来自 Intro to Rx 书:

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...

更好的方法是在您的 viewDidLoad 中执行类似的操作(或从您的 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 { [=10=].element }
    .map { Earthquake.earthquakes(from: [=10=]) }
    .map { [=10=].map { EarthquakeCellDisplay(earthquake: [=10=]) } }
    .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 { [=10=].error }
    .map { (title: "Error", message: [=10=].localizedDescription) }
    .bind { [weak self] title, message in
        self?.presentAlert(title: title, message: message, animated: true)
    }
    .disposed(by: disposeBag)

materialize() 运算符将 Event.error(Error) 结果转换为 Event.next(.error(Error)),这样链就不会被破坏。 .compactMap { [=14=].element } 仅发出成功结果,而 .compactMap { [=15=].error } 仅发出错误。

以上代码改编自我的 RxEarthquake 示例。