1

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

我有类似的东西:

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

4

2 回答 2

7

尝试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)
于 2017-08-03T06:47:12.837 回答
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]>>

让我们完成“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登录分开,以备日后维护是一个不错的选择。看看这个样本,我想它可能会对你有所帮助。

于 2017-08-04T06:28:03.703 回答