Combine框架第三个`collect`方法

Combine framework third `collect` method

在iOS13 Combine框架中,有3个collect运算符方法。前两个很明显,但第三个使用的类型我无法弄清楚。

 collect(_:options:)

https://developer.apple.com/documentation/foundation/timer/timerpublisher/3329497-collect

func collect<S>(_ strategy: Publishers.TimeGroupingStrategy<S>, 
    options: S.SchedulerOptions? = nil) 
    -> Publishers.CollectByTime<Timer.TimerPublisher, S> 
    where S : Scheduler

谁能举例说明如何调用此方法?

经过一番努力,我想出了一个这样的例子:

let t = Timer.publish(every: 0.4, on: .main, in: .default)
t
    .scan(0) {prev,_ in prev+1}
    .collect(.byTime(DispatchQueue.main, .seconds(1))) // *
    .sink(receiveCompletion: {print([=10=])}) {print([=10=])}.store(in:&storage)
let cancellable = t.connect()
delay(3) { cancellable.cancel() }

(其中 storage 是通常的 Set<AnyCancellable> 以保持订阅者存活)。

输出为:

[1, 2]
[3, 4, 5]
[6, 7]

所以我们大约每 0.4 秒发布一个新数字,但 collect 仅每 1 秒发布一次。因此,前两个值到达,发布 12,然后 collect 执行它的操作,累积到目前为止到达的所有值,并将它们发布为数组,[1,2]。等等。每一秒,到目前为止管道中的任何内容都会累积到一个数组中并作为数组发布。

两个 TimeGroupingStrategy 机制已在该枚举中发布。从 iOS 13.3 开始,仍然只有两个:

  • byTime
  • byTimeOrCount

在任何一种情况下,前两个参数都是一个调度程序,运行它们(立即、调度队列、运行循环或操作队列)通常只是根据您传入的内容推断出来。 scheduler 是一个 Stride - 您指定的时间间隔 - 运算符将缓冲值。

byTime 中,它将在您指定的时间间隔内收集和缓冲尽可能多的元素(为此使用无限量的内存)。 byTimeOrCount 将缓冲的项目数量限制为特定计数。

指定这些的两种方法是:

let q = DispatchQueue(label: self.debugDescription)
publisher
    .collect(.byTime(q, 1.0))

let q = DispatchQueue(label: self.debugDescription)
publisher
    .collect(.byTimeOrCount(q, 1.0, 10))

它们使用 DispatchQueue,但您可以轻松地使用任何其他调度程序。 如果您只是为步幅传递一个 Double,它会将其作为以秒为单位的值。

在这两种情况下,当时间(或计数,如果指定了该版本)过去时,操作员将依次向其订阅者发布一组收集的值。