RxSwift 中集合的延迟迭代

Delay iteration of an collection in RxSwift

我的实际需求:

我有一个自定义对象列表,我想延迟迭代它。我不能在我的 for 循环中使用 DispatchQueue.main.asyncAfter,因为我的迭代创建了一个触发 FetchedResultController 并因此更新我的 TableViewCoreData 对象。无论如何,所以我尝试使用 Rx 来迭代我的列表,每次延迟 1 秒。但是我做不到。

问题

我想使用 RxSwift 延迟数组中每个元素的迭代。 我可以在 Java 中做到这一点,但不能在 RxSwift 中做到。

.delay() 运算符也没有帮助,它只是延迟了整个过程。

任何示例都会有所帮助,因此我不会发布任何具体代码...但这是我迄今为止一直在尝试的

var array = [1, 2, 3, 4, 5]

Observable.from(array)
  .delay(RxTimeInterval(5), scheduler: MainScheduler.instance)
  .subscribe { (intValue) in
    print("onNext() \(intValue)")
}

输出

onNext() next(1)
onNext() next(2)
onNext() next(3)
onNext() next(4)
onNext() next(5)
onNext() completed

输出在 5 秒后打印,而不是间隔 5 秒。

我没有得到任何整数值,而是 next(1).

这是一个常见的混淆。如您所知,delay 将平等地应用于每个元素,因此所有元素都会延迟五秒,而不是在每个事件之间放置五秒延迟。 (所以第一个事件立即发生,第二个在五秒后发生,第三个在十秒后发生,依此类推。

一旦您意识到您真正想要做的是在每个事件之间设置延迟,解决方案就会变得更加清晰。或者至少,延迟 from 运算符不起作用的原因应该更清楚。

解决方案是使用其中一种 flatMap 变体:

let array = [1, 2, 3, 4, 5]
Observable.from(array)
    .concatMap { Observable.empty().delay(.seconds(5), scheduler: MainScheduler.instance).startWith([=10=]) }
    .subscribe { (intValue) in
        print("onNext() \(intValue)")
    }

Observable.empty().delay(.seconds(5), scheduler: MainScheduler.instance).startWith([=14=]) 将立即发出值,但在发出完成的事件之前等待五秒钟。

concatMap 运算符在每个传入事件上调用闭包并将生成的 Observable 连接在一起,以便在前一个完成之前不会订阅后续 Observable。

在我的文章中了解更多相关信息,The Many Faces of FlatMap


基于 Sandeep Bhandari 对该问题所写评论的替代解决方案是使用间隔来限制 from 运算符何时可以发出值。像这样:

let array = [1, 2, 3, 4, 5]
Observable.zip(Observable.from(array), Observable<Int>.interval(.seconds(5), scheduler: MainScheduler.instance).take(while: { [=11=] != array.count }))
    .map { [=11=] }
    .subscribe { (intValue) in
        print("onNext() \(intValue)")
    }