通过 AudioPlayer 上的委托方法更新 UIProgressView

Updating UIProgressView via delegate method on AudioPlayer

我正在尝试 . Here's CADisplayLink's initialiation signature

这里是 MyAudioPlayer class.

相关变量的总结
protocol AudioPlayerDelegate: class {
    func updateSlider(sender: AudioPlayer)
}

class AudioPlayer: NSObject {
    // relevant vars
    var updater: CADisplayLink?
    weak var delegate: AudioPlayerDelegate?

    func play() {
        // some setup stuff

        updater = CADisplayLink(target: self, selector: #selector(delegate?.updateSlider(sender:)))

        // regular stuff to play an audio file
    }
}

当我在 play() 方法中初始化 updater 时,编译器说:

Argument of #selector refers to instance method updateSlider(sender:) that is no exposed to Objective-C.

很简单...在 func updateSlider(sender: AudioPlayer) 前面添加 objc,像这样:

@objc func updateSlider(sender: AudioPlayer)

编译器错误消失一纳秒,然后我刚刚更新的行说:

@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes.

a few answers covering this topic,但我还没找到合适的。

我尝试将 updateSlider 放在扩展中而不是协议部分,但我一直收到编译器的乒乓球要在前面添加 @objc 然后要删除它。

我也尝试使用 Timer class 的实例而不是 CADisplayLink class 来执行此操作,但我遇到了同样的问题。

感谢您的阅读。我欢迎你的建议。

可以这样修复:)

func play() {
    // some setup stuff

    updater = CADisplayLink(target: self, selector: #selector(updateSlider(sender:)))

    // regular stuff to play an audio file
}

func updateSlider(sender: AudioPlayer) {
    delegate?.updateSlider(sender: sender)
}

Dan 在这个问题上帮助我完成了任务。我需要在协议声明前添加 @objc,而不是仅在我的委托方法前添加 @objc

// First change
@objc protocol AudioPlayerDelegate: class {
    @objc func updateSlider(sender: AudioPlayer)
}

再往下 AudioPlayer class...

// Delegate declaration
weak var delegate: AudioPlayerDelegate?

// Second Change
if let delegate = delegate {
    updater = CADisplayLink(target: delegate, selector: #selector(AudioPlayerDelegate.updateSlider(sender:)))
    updater?.preferredFramesPerSecond = 30
    updater?.add(to: RunLoop.current, forMode: .commonModes)
}

最后,当 updater 完成后,使它无效并将其清除(最有可能以您用来停止 AVAudioPlayer 实例的任何方法。

    updater?.invalidate()
    updater = nil