RxSwift 使 Observable 触发一个主题

Posted

技术标签:

【中文标题】RxSwift 使 Observable 触发一个主题【英文标题】:RxSwift Make Observable trigger a subject 【发布时间】:2020-05-24 14:47:30 【问题描述】:

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

除此之外,我还有一个拉动刷新,它创建了一个可观察的更新数据并更新 BehaviorSubject 中的数据,以便我的 UITableView 正确更新。

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

我想到的几个选项是:

    订阅观察者的onError,拨打我的BehaviorSubjectonError\ 以某种方式尝试concat?或bind(to: ..) 让我的ViewController 中的另一个订阅者订阅,除了我的tableview 订阅BehaviorSubject

有什么建议吗?

【问题讨论】:

【参考方案1】:

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

主题的使用应该主要停留在样本和测试领域。主题是开始使用 Rx 的好方法。它们缩短了新开发人员的学习曲线,但也带来了一些问题......

最好在您的 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  $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)

materialize() 运算符将Event.error(Error) 结果转换为Event.next(.error(Error)),这样链就不会被破坏。 .compactMap $0.element 只发出成功的结果,而.compactMap $0.error 只发出错误。

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

【讨论】:

以上是关于RxSwift 使 Observable 触发一个主题的主要内容,如果未能解决你的问题,请参考以下文章

RxSwift:多次连接到 Connectable Observable

使用 RxSwift 触发的两个事件

在 RxSwift 中,我如何对 observable 未发送任何事件进行单元测试?

按下按钮时可观察到 RxSwift 触发器

RxSwift:延迟 observable 直到另一个 observable 完成?

RxSwift - 一个 Observable 中的多个 Observable 值