问题
I would like to create an Observable from anyCollection that will emit each element one by one, after a delay. Also, onNext I would like to perform some updates to the item (model).
For example:
// Feed all dogs, one by one, with an interval of 5 seconds.
class Dog {
var name: String?
var age: Int?
var feeded = false
init(_ name: String, _ age: Int){
self.name = name
self.age = age
}
}
func feedDogs(){
let dog1 = Dog("Ren", 3)
let dog2 = Dog("Bega", 7)
let dog3 = Dog("Xuxu", 11)
let delay = 6 // seconds
let allDogs = [dog1, dog2, dog3]
// Observable....
// Expected results after subscribe
// Start - > 0 seconds
// dog1.feeded // true
// time lapse -> 6 seconds
// dog2. feeded // true
// timelapse -> 12 seconds
// dog3.feeded // true
}
I tried to use "zip" like "zipWith" (in RxJava), but it seems that in RxSwift is not supported.
回答1:
Well... after some R&D this is a tested working version for my question.
Observable.zip(Observable.from(allDogs), Observable<Int>.interval(RxTimeInterval(delay), scheduler: MainScheduler.instance)).subscribe(onNext: { (dog, index) in
print(dog.name)
}
)
回答2:
I wrote extension for this purpose.
extension Observable {
func with(interval: RxTimeInterval) -> Observable {
return enumerated()
.concatMap { index, element in
Observable
.just(element)
.delay(index == 0 ? RxTimeInterval.seconds(0) : interval,
scheduler: MainScheduler.instance)
}
}
}
Sample:
Observable.from([1, 2, 3, 4, 5])
.with(interval: RxTimeInterval.seconds(1))
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
回答3:
Hmm, the simplest way I can think of (may not be so elegant though) is this.
You create a timer.
let timer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(count), userInfo: nil, repeats: true)
and a counter
var counter : Int = 0
and in the selector do this
@objc func count(){
print("i am being here")
rxTimer.value = ()
}
where rxTimer is a defined variable
var rxTimer = Variable<(())>(())
then you simply call the observe the rxTimer as such
rxTimer.asDriver()
.map { (_) -> Int? in
if self.counter == collection.count{
timer.invalidate()
return nil
}
let value = collection[self.counter]
self.counter += 1
return value
}
.filter{$0 != nil}
.map{$0!}
where collectio is your defined collection. Here I define it to be an int, but you can define it to be anything you want.
来源:https://stackoverflow.com/questions/47466268/how-to-emit-items-one-by-one-from-collection-with-a-delay-in-rxswift