🍁

NotificationCenter.default.publisher.valuesが値を取りこぼさないようにするワークアラウンド

に公開

任意の遠隔地同士の情報伝達手段として(おそらくアンチパターンではあるが)NotificationCenterを使う場合があります。

import Foundation

extension Notification.Name {
    public static let debugSleep = Notification.Name("debugSleep")
}
struct Context {}

// Aの地点
let context = Context() // 伝達したい情報
NotificationCenter.default.post(name: .debugSleep, object: context)

// Bの地点
Task {
    let publisher = NotificationCenter.default.publisher(for: .debugSleep)
    for await value in publisher.values {
        print(value.object as! Context)
    }
}

しかし、どうもpostする間隔が非常に短いと値を取りこぼして受け取ってしまうようです。

そういう時は値をバッファして受け取れるようにします。

extension Publisher where Self.Failure == Never {
    func bufferedValues() -> AsyncPublisher<Publishers.Buffer<Self>> {
        self.buffer(size: 5, prefetch: .keepFull, whenFull: .dropOldest)
            .values
    }
}

// Bの地点
Task {
    let publisher = NotificationCenter.default.publisher(for: .debugSleep)
    for await value in publisher.bufferedValues() {
        print(value.object as! Context)
    }
}

バッファのsizeは値を取りこぼさなくなるまで調節します。

Discussion