链接RxSwift可观察到不同类型

时间:2017-08-02 22:24:06

标签: ios swift rx-swift rx-cocoa

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

我有类似的东西:

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实现它?我阅读了文档和示例,但了解如何链接具有相同类型的observable

2 个答案:

答案 0 :(得分:4)

尝试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)

答案 1 :(得分:0)

我认为获取模型的方法应该驻留在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]>>

让我们完成&#39; TODO&#39;

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和VC分开是一个不错的选择。 ViewModel登录以供将来维护。看看this sample,我认为它可能对你有所帮助。

相关问题