【问题标题】:How to emit items, one by one, from Collection with a delay in RxSwift如何在 RxSwift 中延迟从 Collection 中逐一发出项目
【发布时间】:2017-11-24 04:12:19
【问题描述】:

我想从 anyCollection 创建一个 Observable,它会在延迟后一个一个地发出每个元素。另外,onNext 我想对项目(模型)进行一些更新。

例如:

// 以 5 秒的间隔,一只一只地喂所有的狗。

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
}

我尝试使用“zipWith”之类的“zip”(在 RxJava 中),但似乎在 RxSwift 中不受支持。

【问题讨论】:

  • .zip() 绝对是要走的路,它有什么问题? Observable.zip(Observable.from(allDogs), timer) { /* ... */ }

标签: swift rx-swift


【解决方案1】:

嗯...经过一些研发,这是我的问题的测试工作版本。

Observable.zip(Observable.from(allDogs), Observable<Int>.interval(RxTimeInterval(delay), scheduler: MainScheduler.instance)).subscribe(onNext: { (dog, index) in
            print(dog.name)
        }
    )

【讨论】:

    【解决方案2】:

    我为此编写了扩展程序。

    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)
                }
        }
    
    }
    

    示例:

    Observable.from([1, 2, 3, 4, 5])
        .with(interval: RxTimeInterval.seconds(1))
        .subscribe(onNext: {
            print($0)
        })
        .disposed(by: disposeBag)
    

    【讨论】:

      【解决方案3】:

      嗯,我能想到的最简单的方法(虽然可能不那么优雅)就是这样。

      您创建了一个计时器。

      let timer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(count), userInfo: nil, repeats: true)
      

      还有一个计数器

       var counter : Int = 0
      

      在选择器中这样做

      @objc func count(){
          print("i am being here")
          rxTimer.value = ()
      }
      

      其中 rxTimer 是一个已定义的变量

      var rxTimer = Variable<(())>(())
      

      然后您只需将观察器称为 rxTimer

      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!}
      

      其中 collectionio 是您定义的集合。这里我将它定义为一个 int,但你可以将它定义为任何你想要的。

      【讨论】:

      • @programmingBeignner:不应该这么复杂:)。恕我直言,一切都可以用 Rx 语法和方法来完成。
      猜你喜欢
      • 2015-03-26
      • 1970-01-01
      • 2016-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多