【问题标题】:AVPlayer's addPeriodicTimeObserver function is not being executed properlyAVPlayer 的 addPeriodicTimeObserver 函数没有正确执行
【发布时间】:2018-05-12 19:52:21
【问题描述】:

背景

我正在尝试在 macOS 应用程序中设置一个非常基本的音频播放器。我在 ma​​cOS 10.13.4 上使用 Xcode 9.3


设置

我有一个MediaManager 类来控制AVPlayer 对象:

let EPISODE_SELECTED_KEY = "EPISODE_SELECTED"

class MediaManager {
    
    static var shared: MediaManager = MediaManager()
    
    var player: AVPlayer?
    
    var currentFile: URL? {
        didSet {
            if (currentFile != nil) {
                play(URL: currentFile!)
                NotificationCenter.default.post(name: NSNotification.Name(EPISODE_SELECTED_KEY), object: nil)
            }
        }
    }

    
    func play(URL: URL) {
        let item = AVPlayerItem(url: URL)
        player = AVPlayer(playerItem: item)
        player?.play()
    }

}

为了直观地跟踪正在播放的音频项目的进度,我将NSSlider 子类化如下:

class PlayerSlider: NSSlider {
    
    var observerToken: Any?
    var mediaManager = MediaManager.shared
    
    override var isEnabled: Bool {
        didSet {
            // Register for PlayerManager notification.
            NotificationCenter.default.addObserver(self, selector: #selector(setupPlayerObserver), name: Notification.Name(EPISODE_SELECTED_KEY), object: nil)
        }
    }
    
    override var doubleValue: Double {
        didSet {
            // Make sure the player has an active item.
            guard mediaManager.currentEpisode != nil || mediaManager.currentFile != nil else {
                return
            }
            // Update player with slider's position.
            let seekTime = CMTime(seconds: (mediaManager.player?.currentTime().seconds)! * (doubleValue / 100), preferredTimescale: CMTimeScale(NSEC_PER_SEC))
            mediaManager.player?.seek(to: seekTime)
        }
    }
    
    @objc func setupPlayerObserver() {
        // Setup observer to update UI every 0.5 seconds.
        let interval = CMTime(seconds: 0.5, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
        self.observerToken = mediaManager.player!.addPeriodicTimeObserver(forInterval: interval, queue: .main, using: { (time) in
            // Update slider value to audio item progress.
            let duration = self.mediaManager.player!.currentItem!.duration.seconds
            let seekTime = self.mediaManager.player!.currentTime().seconds
            self.doubleValue = seekTime / duration * 100
        })
        
    }
}

出于测试目的,我只是将MediaManager 单例的currentFile 属性设置为本地文件。


问题

在我传递给addPeriodicTimeObserver 函数的块中,如果我注释掉文件播放正常的所有内容。但是,如果那里甚至有一个 print 语句,则什么也不会发生。该文件从不播放,应用程序只是挂起。


问题

  1. 该块内发生了什么?即使是单个语句也会阻止 AVPlayer 播放。
  2. 这是音频文件播放器的好设计吗?让MediaManager 单例和PlayerSlider 中的侦听器。

【问题讨论】:

    标签: swift macos notifications avfoundation appkit


    【解决方案1】:

    您所写的是要求定期观察者每 0.5*109 秒给您回电一次,但 0.5 向下舍入为 0,因此是每 0 秒一次。两者都不可能(为什么addPeriodicTimeObserver 没有提到这一点?),所以试试

    let interval = CMTime(value: 1, timescale: 10)  // every tenth of a second, say
    

    【讨论】:

    • 你说得对,我是想写CMTime(value: 1, timescale: 10)。我想我是自动补全的受害者。那一定是一个非常缓慢的周期性观察者。更新。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2018-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-02
    • 1970-01-01
    相关资源
    最近更新 更多