Combine Publisher 没有为 KVO 触发 属性

Combine Publisher not firing for a KVO property

我正在尝试通过其 Combine Publisher 跟踪 AVAudioPlayerNode 的播放状态:

import Cocoa
import AVFoundation
import Combine

@main
class AppDelegate: NSObject, NSApplicationDelegate {

    let engine = AVAudioEngine()
    let player = AVAudioPlayerNode()
    var cancellable: AnyCancellable?

    func applicationDidFinishLaunching(_ aNotification: Notification) {

        cancellable = player.publisher(for: \.isPlaying)
            .sink { newValue in
                print("is playing: \(newValue)")
            }

        let url = Bundle.main.url(forResource: "blues", withExtension: "aiff")!
        let file = try! AVAudioFile(forReading: url)

        let buffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat, frameCapacity: UInt32(file.length))!
        try! file.read(into: buffer)

        engine.attach(player)
        engine.connect(player, to: engine.mainMixerNode, format: file.processingFormat)

        player.scheduleBuffer(buffer, at: nil, options: .loops, completionHandler: nil)

        try! engine.start()
        player.play()
    }
}

接收器在初始化时只被调用一次,以后不会再调用。我希望它在播放开始时被调用,但它没有...任何想法为什么?

AVAudioPlayerNode 似乎不符合 isPlaying 属性 的 KVO。通常当属性符合 KVO 时,文档会明确提及,但 docs for AVAudioPlayerNode 不会直接解决它

我 运行 使用 addObserver(_:forKeyPath:options:context:) 进行了简单测试,并确认在调用 play()stop() 时不会发出 KVO 通知。

至于 Combine 发布者存在的原因,我假设 NSObject.KeyValueObservingPublisher 适用于所有 ObjC @property 声明,无论 ObjC class 是否在内部处理 属性一种符合 KVO 的方式(通过发送 -willChangeValueForKey:-didChangeValueForKey:)。