🌾
[Swift] [Combine] measureInterval(using:)を使って出力の間隔を取得する
measureInterval(using:)
Combine には measureInterval(using:)
という Publisher の出力の間隔を取得することができる関数が用意されているのでそれを紹介してみたいと思います。
サンプルコード
挙動はサンプルコードを見ていただくのが早いと思います。
まずは以下のような一定間隔で出力してくれる Publisher を用意します。
import Combine
import Foundation
var cancellables = Set<AnyCancellable>()
let timerPublisher = Timer.publish(every: 2, on: .main, in: .default)
.autoconnect()
.share()
適当に subscribe すると以下のような出力になります。
timerPublisher
.sink { output in
print("timerPublisher: \(output)")
}
.store(in: &cancellables)
// timerPublisher: 2022-02-05 11:14:17 +0000
// timerPublisher: 2022-02-05 11:14:19 +0000
// timerPublisher: 2022-02-05 11:14:21 +0000
ここで、measureInterval(using:)
を間に噛ませると以下のようになります。
timerPublisher
.measureInterval(using: RunLoop.main)
.sink { output in
print("measureInterval: \(output)")
}
.store(in: &cancellables)
// measureInterval: Stride(magnitude: 2.0009289979934692)
// measureInterval: Stride(magnitude: 1.9993009567260742)
// measureInterval: Stride(magnitude: 1.9998070001602173)
measureInterval(using:)
を間に噛ませることで、時刻
から 時間間隔
に変更されていることがわかります。
timerPublisher
.measureInterval(using: RunLoop.main)
.sink { output in
print("measureInterval: \(output)")
}
.store(in: &cancellables)
// measureInterval: Stride(magnitude: 0.20106804370880127)
// measureInterval: Stride(magnitude: 0.1994309425354004)
// measureInterval: Stride(magnitude: 0.19979500770568848)
さらに collect()
を間に噛ませて、ちょっとした関数を当ててあげるだけで、出力の間隔の平均を表すこともできます。
func averageInterval(strides: [RunLoop.SchedulerTimeType.Stride]) -> Double {
let sum = strides.map { $0.timeInterval }.reduce(0, +)
return Double(sum) / Double(intervalValues.count)
}
timerPublisher
.measureInterval(using: RunLoop.main)
.collect(10)
.map { averageInterval(strides: $0) }
.sink { output in
print("output average interval(s): \(output)")
}
.store(in: &cancellables)
// output average interval(s): 2.0000609040260313
以上になります。
Discussion