How to emit items, one by one, from Collection with a delay in RxSwift

对着背影说爱祢 提交于 2020-05-15 05:41:11

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!