如何限制 observable 直到条件变为真
Posted
技术标签:
【中文标题】如何限制 observable 直到条件变为真【英文标题】:How to throttle observable until a condition becomes true 【发布时间】:2020-02-01 20:10:21 【问题描述】:我的应用中有一个集合视图,当有新内容或删除时,它会以动画形式刷新。但是,我不希望它在用户滚动时刷新,因为它会导致抽搐。我只想在用户完成滚动/不滚动时刷新集合视图。
所以我有一个数据源驱动程序,我尝试使用filter
让它等到它变成真的但没有运气。
这是我传递给ViewModel
的滚动驱动程序
let isScrollViewScrollingDriver = Observable.merge(
gridCollectionView.rx.willBeginDragging.map _ in true ,
gridCollectionView.rx.didEndDragging.map _ in false
).asDriver(onErrorJustReturn: false).startWith(false).distinctUntilChanged()
我在视图控制器中的 ViewModel 初始化
viewModel = ViewModel(
photoLibraryService: PhotoLibraryService.shared,
isGridViewScrolling: isScrollViewScrollingDriver,
disposeBag: disposeBag
)
我的视图模型
let assetDriver = photoLibraryService.albumDriver.asObservable()
.withLatestFrom(
isGridViewScrolling.asObservable().filter $0 == false
) (arg0, arg1) in
return arg0
.flatMapLatest libraryAlbum -> Observable<[LibraryAsset]> in
return photoLibraryService.convert(album: libraryAlbum)
.asDriver(onErrorJustReturn: []).startWith([]).distinctUntilChanged()
然后我将assetDriver 映射到驱动我的集合视图的dataSourceDriver。
我可以对assetDriver 进行哪些更改以使其等待isGridViewScrolling
变为false
?谢谢。
【问题讨论】:
试试我几年前在 .NET 中提供的这个答案。没有使用 rx-swift 所以一些运营商可能有不同的名字,但我认为它可以满足你的需要:***.com/questions/23431018/… 谢谢!!我会试着把它翻译回 Swift 看看它是否有效! 【参考方案1】:听起来你需要我的stallUnless(_:initial:)
运算符。 https://gist.github.com/danielt1263/2b624d7c925d8b7910ef2f1e5afe177b
/**
Emits values immediately if the boundary sequence last emitted true, otherwise collects elements from the source sequence until the boundary sequence emits true then emits the collected elements.
- parameter boundary: Triggering event sequence.
- parameter initial: The initial value of the boundary
- returns: An Observable sequence.
*/
func stallUnless<O>(_ boundary: O, initial: Bool) -> Observable<Element> where O: ObservableType, O.Element == Bool
return Observable.merge(self.map(Action.value), boundary.startWith(initial).distinctUntilChanged().materialize().map(Action.trigger).takeUntil(self.takeLast(1)))
.scan((buffer: [Element](), trigger: initial, out: [Element]()), accumulator: current, new in
switch new
case .value(let value):
return current.trigger ? (buffer: [], trigger: current.trigger, out: [value]) : (buffer: current.buffer + [value], trigger: current.trigger, out: [])
case .trigger(.next(let trigger)):
return trigger ? (buffer: [], trigger: trigger, out: current.buffer) : (buffer: current.buffer, trigger: trigger, out: [])
case .trigger(.completed):
return (buffer: [], trigger: true, out: current.buffer)
case .trigger(.error(let error)):
throw error
)
.flatMap $0.out.isEmpty ? Observable.empty() : Observable.from($0.out)
【讨论】:
【参考方案2】:你可以使用 combineLatest:
let assetDriver = Driver
.combineLatest(
photoLibraryService.albumDriver,
isGridViewScrolling
)
.filter !$1
.map $0.0
.flatMapLatest libraryAlbum -> Driver<[LibraryAsset]> in
photoLibraryService.convert(album: libraryAlbum)
.asDriver(onErrorJustReturn: [])
.startWith([])
.distinctUntilChanged()
【讨论】:
以上是关于如何限制 observable 直到条件变为真的主要内容,如果未能解决你的问题,请参考以下文章
如何从我的数组列表中删除 __ob__: Observer?
如何在 vuejs 中获取价值 [__ob__: Observer]