如何将多个驱动程序与 RxSwift 正确组合?

Posted

技术标签:

【中文标题】如何将多个驱动程序与 RxSwift 正确组合?【英文标题】:How to properly combine multiple Drivers with RxSwift? 【发布时间】:2017-07-11 16:39:21 【问题描述】:

我正在将 viewDidAppearfilter 驱动程序与 RxSwift 结合使用。他们工作得很好。但是当我介绍第三个驱动程序时,它会停止在最新的联合收割机上调用flatMapLatest

在我的视图控制器中,我有这些驱动程序:

let filter: Driver<String>
let viewDidAppear: Driver<Void>
let refresh: Driver<Void>

在我的视图模型中:

// On viewDidAppear, I download a list of portfolios

let viewDidAppearPortfolios = viewDidAppear
    .flatMapLatest( (_) -> Driver<Result<[PortfolioModel]>> in        
        return networkService.request(Router.portfolios)!
            .responseCollections()
            .trackActivity(fetching)
            .asDriver(onErrorJustReturn: .failure(NSError()))

    )
    .flatMapLatest( (result: Result<[PortfolioModel]>) -> Driver<[PortfolioModel]> in

        switch result 
        case .success(let value): return Driver.just(value)
        case .failure(_): return Driver.just([])
        

    )

// Then I combine with a filter from my search bar.

self.portfolios = Driver.combineLatest(viewDidAppearPortfolios, filter)
    .flatMapLatest  (portfolios: [PortfolioModel], filter: String) -> Driver<[PortfolioModel]> in

        if filter.isEmpty 
            return Driver.just(portfolios)
        

        return Driver.just(portfolios.filter( (portfolio) -> Bool in
            portfolio.portfolio.localizedCaseInsensitiveContains(filter)
        ))

    

以上方法有效!

网络请求一个投资组合列表,并且我可以在客户端输入时过滤这些结果。

但是,我希望用户拉动刷新,然后再次触发网络请求!因此,我结合了我的刷新驱动程序。

还有这个:

Driver.combineLatest(viewDidAppearPortfolios, filter)

变成这样:

Driver.combineLatest(viewDidAppearPortfolios, filter, refresh)

问题!

refresh 结合后,flatMapLatest 不再在 viewDidAppear 上调用!仅当我手动 pullToRefresh 时。

Driver.combineLatest(viewDidAppearPortfolios, filter, refresh).flatMapLatest  _,_,_ in 
    // No longer get's called on viewDidAppear after combining with refresh

    viewDidAppearPortfolios 还在执行,所以网络请求 正在被调用! 只有当我手动拉动刷新时,我才能得到 我之前要求的作品集列表...

知道为什么吗?

谢谢!

【问题讨论】:

【参考方案1】:

您的 refresh 似乎还没有发出单个事件,因此未计算 combineLatest。 我试过这段代码来测试:

let one = Driver.just(1)
let two = Driver.just(2)
let three: Driver<Int> = .just(3)

let result = Driver.combineLatest(one, two, three)
    .flatMapLatest 
        return Driver.just($0 + $1 + $2)
    

result.drive(onNext: 
    print($0)
)

这会打印 6 但如果您使用 let three: Driver&lt;Int&gt; = .empty() 这不会打印任何内容。所以我猜你需要一种方法来将初始值设置为refresh 流。

【讨论】:

就是这样,谢谢。就我而言,我将startWith 添加到我的refreshControl:refreshControl.rx.controlEvent(.valueChanged).startWith(()).asDriver(onErrorJustReturn: ()) Driver.combineLatest 对我来说是 omg。我一直在使用 Observables.merge 来处理那些包含在 .asObservable() 中的驱动程序。

以上是关于如何将多个驱动程序与 RxSwift 正确组合?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 RxSwift 转换为组合框架

如何使用 RxSwift 和 RxSwiftDataSources 将表视图与表示不同数据类型的多个部分绑定?

如何在 RxSwift 中将多个数据模型绑定到 TableView

如何正确安装“RxSwift”模块?

RxSwift:将 PublishSubject 绑定到多个按钮并接收发送者

rxswift:如何获取 Observable<Any> 导致 Observable<[Category]> 的组合?