链接不同类型的 RxSwift observable

Chaining RxSwift observable with different type

我需要从网络请求不同类型的模型,然后将它们组合成一个模型。 如何链接多个可观察对象和 return 另一个可观察对象?

我有类似的东西:

func fetchDevices() -> Observable<DataResponse<[DeviceModel]>>

func fetchRooms() -> Observable<DataResponse<[RoomModel]>>

func fetchSections() -> Observable<DataResponse<[SectionModel]>> 

我需要做类似的事情:

func fetchAll() -> Observable<(AllModels, Error)> {
    fetchSections()

    // Then if sections is ok I need to fetch rooms
    fetchRooms()

    // Then - fetch devices
    fetchDevices()

    // And if everything is ok create AllModels class and return it
    // Or return error if any request fails
    return AllModels(sections: sections, rooms: rooms, devices:devices)
  }

如何用RxSwift实现?我阅读了文档和示例,但了解如何将相同类型的可观察对象链接起来

尝试 combineLatest 运算符。您可以组合多个可观察对象:

let data = Observable.combineLatest(fetchDevices, fetchRooms, fetchSections) 
    { devices, rooms, sections in
        return AllModels(sections: sections, rooms: rooms, devices:devices)
    }
    .distinctUntilChanged()
    .shareReplay(1)

然后,您订阅它:

data.subscribe(onNext: {models in 
    // do something with your AllModels object 
})
.disposed(by: bag)

我认为获取模型的方法应该驻留在 ViewModel 中,并且应该等待一个事件一起开始调用它们,否则它们不会启动 运行。

假设有一个按钮调用你的三个方法,如果函数调用成功,将启用另一个按钮。

考虑 ViewController 中的 ViewModel。

let viewModel = ViewModel()

在 ViewModel 中,像这样声明抽象的 I/O 事件,

struct Input {
    buttonTap: Driver<Void>  
}
struct Output {
    canProcessNext: Driver<Bool>
}

然后您可以通过在 ViewModel 中创建这样的函数,将您的输入清楚地转换为输出。

func transform(input: Input) -> Output {
    // TODO: transform your button tap event into fetch result.

}

在 viewDidLoad,

let output = viewModel.transform(input: yourButton.rx.tap.asDriver())
output.drive(nextButton.rx.isEnabled).disposed(by: disposeBag)

现在一切就绪,但结合您的三种方法 - 将它们放入 ViewModel。

func fetchDevices() -> Observable<DataResponse<[DeviceModel]>>
func fetchRooms() -> Observable<DataResponse<[RoomModel]>>
func fetchSections() -> Observable<DataResponse<[SectionModel]>>

让我们完成'TODO'

let result = input.buttonTap.withLatestFrom(
    Observable.combineLatest(fetchDevices(), fetchRooms(), fetchSections()) { devices, rooms, sections in
    // do your job with response data and refine final result to continue
    return result
}.asDriver(onErrorJustReturn: true))

return Output(canProcessNext: result)

我写的不仅仅是让它工作,而且还考虑了您的应用程序的整体设计。把所有东西都放在 ViewController 里面不是办法,尤其是使用 Rx 设计。我认为将 VC 和 ViewModel 登录分开以备将来维护是个不错的选择。看看this sample,我想它可能对你有帮助。