如何在条件变为真之前限制可观察的
How to throttle observable until a condition becomes true
我的应用程序中有一个集合视图,当有新内容或删除内容时,它会以动画方式刷新。但是,我不希望它在用户滚动时刷新,因为这会导致抖动。我只想在用户完成滚动/不滚动时刷新集合视图。
所以我有一个数据源驱动程序,我尝试使用 filter
让它等到它变为 true 但没有运气。
这是我传递给 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 { [=12=] == 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
?谢谢。
听起来你需要我的 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 { [=10=].out.isEmpty ? Observable.empty() : Observable.from([=10=].out) }
}
}
您可以使用 combineLatest:
let assetDriver = Driver
.combineLatest(
photoLibraryService.albumDriver,
isGridViewScrolling
)
.filter { ! }
.map { [=10=].0 }
.flatMapLatest { libraryAlbum -> Driver<[LibraryAsset]> in
photoLibraryService.convert(album: libraryAlbum)
.asDriver(onErrorJustReturn: [])
}
.startWith([])
.distinctUntilChanged()
我的应用程序中有一个集合视图,当有新内容或删除内容时,它会以动画方式刷新。但是,我不希望它在用户滚动时刷新,因为这会导致抖动。我只想在用户完成滚动/不滚动时刷新集合视图。
所以我有一个数据源驱动程序,我尝试使用 filter
让它等到它变为 true 但没有运气。
这是我传递给 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 { [=12=] == 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
?谢谢。
听起来你需要我的 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 { [=10=].out.isEmpty ? Observable.empty() : Observable.from([=10=].out) }
}
}
您可以使用 combineLatest:
let assetDriver = Driver
.combineLatest(
photoLibraryService.albumDriver,
isGridViewScrolling
)
.filter { ! }
.map { [=10=].0 }
.flatMapLatest { libraryAlbum -> Driver<[LibraryAsset]> in
photoLibraryService.convert(album: libraryAlbum)
.asDriver(onErrorJustReturn: [])
}
.startWith([])
.distinctUntilChanged()