Swift 组合自定义发布者:存储对订阅者数组的引用?

NRi*_*itH 6 swift combine

我正在尝试编写一个自定义组合Publisher,它将从AVAudioEngine水龙头发送分贝和时间戳。在浏览了大量教程和 WWDC 视频之后,我仍然找不到如何Publisher跟踪Subscriber已订阅它的 s 的示例。

public typealias AudioVolume = Double

public struct AudioVolumePublisher: Publisher {
    public typealias Output = AudioVolume
    public typealias Failure = Error
}

public class AudioVolumeSubscription<S: Subscriber>: NSObject, Subscription {
    private var subscriber: S?
    public var combineIdentifier = CombineIdentifier()

    public init(for subscriber: S) {
        self.subscriber = subscriber
    }

    public func request(_ demand: Subscribers.Demand) {
        ...
    }

    public func cancel() {
        subscriber = nil
    }
}

Run Code Online (Sandbox Code Playgroud)

我假设AudioVolumePublisher应该存储其活跃订阅者的列表,但添加一个属性,例如

var subscribers = [S]()
Run Code Online (Sandbox Code Playgroud)

不会编译,因为Subscriber有关联的类型。这是否是处理 s 的正确方法Subscriber?如果是,那么存储它们的最佳方法是什么?类型擦除是我唯一实用的选择吗?

Gil*_*man 5

您可以通过 或 来实现您的CurrentValueSubject目标PassthroughSubject

假设这是您要发送的形状:

struct AudioVolume {
  let decimal: Decimal
  let timestamp: TimeStamp
}
Run Code Online (Sandbox Code Playgroud)

实例化主题

let audioPublisher = PassthroughSubject<AudioVolume, Never>()
Run Code Online (Sandbox Code Playgroud)

每当您需要发布新值时:

let audioVolume = AudioVolume(....)
audioPublisher.send(audioVolume)
Run Code Online (Sandbox Code Playgroud)

每当您需要订阅发布者时:

audioPublisher
  .sink { audioVolume in
    // do something with audioVolume
  }
  .store(in: &cancellables) // retain the subscription in cancellables as long as you want to remain subscribed
Run Code Online (Sandbox Code Playgroud)