如何将多个驱动程序与 RxSwift 正确组合?
How to properly combine multiple Drivers with RxSwift?
我正在将 viewDidAppear
和 filter
驱动程序与 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
还在执行,所以网络请求
正在被调用!
- 只有我手动拉动刷新才能得到
我之前请求的投资组合列表...
知道为什么吗?
谢谢!
看起来你的 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([=10=] + + )
}
result.drive(onNext: {
print([=10=])
})
这会打印 6,但如果您使用 let three: Driver<Int> = .empty()
,则不会打印任何内容。所以我猜你需要一种方法来为 refresh
stream.
设置一个初始值
我正在将 viewDidAppear
和 filter
驱动程序与 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
还在执行,所以网络请求 正在被调用!- 只有我手动拉动刷新才能得到 我之前请求的投资组合列表...
知道为什么吗?
谢谢!
看起来你的 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([=10=] + + )
}
result.drive(onNext: {
print([=10=])
})
这会打印 6,但如果您使用 let three: Driver<Int> = .empty()
,则不会打印任何内容。所以我猜你需要一种方法来为 refresh
stream.