代码之家  ›  专栏  ›  技术社区  ›  Vitalii Gozhenko

不同类型的可观察链RxSwift

  •  1
  • Vitalii Gozhenko  · 技术社区  · 7 年前

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

    我有这样的想法:

    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实现它?我阅读了文档和示例,但了解如何将观察值链接到同一类型

    2 回复  |  直到 7 年前
        1
  •  7
  •   xandrefreire    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)
    
        2
  •  0
  •   DragonCherry    7 年前

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

    假设有一个按钮调用了您的三个方法,如果函数调用成功,还有一个按钮将被启用。

    let viewModel = ViewModel()
    

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

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

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

    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设计。我认为划分风险投资和风险投资是一个很好的选择;查看模型登录以备将来维护。查看 this sample ,我想这可能对你有帮助。