Ios AVPlayer和AVPlayerItem状态何时更改?

Ios AVPlayer和AVPlayerItem状态何时更改?,ios,swift,xcode,avfoundation,avplayer,reasonforwaitingtoplay,Ios,Swift,Xcode,Avfoundation,Avplayer,Reasonforwaitingtoplay,我正在使用AVFoundation开发一个音乐播放器插件,我想在iOS和Android上创建一个统一的界面 我想捕获AVPlayer可能引发的错误,例如,当给定的AVPlayerItem无效时(包含不受支持的文件的URL,如png文件) 我希望AVPlayer.replace()在AVPlayerItem或AVPlayer的状态中引发异常或更改,或者至少在NSNotificationCeter上引发一些相关通知。我试着听/观察他们,但没有一个人报告任何错误。事实上,AVPlayer报告了“准备播

我正在使用AVFoundation开发一个音乐播放器插件,我想在iOS和Android上创建一个统一的界面

我想捕获
AVPlayer
可能引发的错误,例如,当给定的
AVPlayerItem
无效时(包含不受支持的文件的
URL
,如
png
文件)

我希望
AVPlayer.replace()
AVPlayerItem
AVPlayer
的状态中引发异常或更改,或者至少在
NSNotificationCeter
上引发一些相关通知。我试着听/观察他们,但没有一个人报告任何错误。事实上,
AVPlayer
报告了“准备播放”状态

我是一名android开发人员,无法理解
AVPlayer
的工作原理。我怎样才能做到这一点

注意:我不能使用
AVAudioPlayer
,因为文档说明在播放来自网络或可能有延迟的源的音乐时不应使用它

self.mediaPlayer?.replaceCurrentItem(with: nil)
self.mediaPlayer?.play()

即使此代码不会生成错误

您也可以借助AVplayer的属性跟踪播放器的状态

当timeControlStatus的值为AVPlayerItemControlStatusWaitingToplayatsSpecifiedRate时,此属性描述播放机当前等待的原因。否则是零。 您可以使用reasonForWaitingToPlay的值有条件地显示指示播放器等待状态的UI。 此属性是可观察的关键值。 可能的值为AVPLAYERWAITING WITH NOITEM TO LAYREASON、AVPLAYERWAITING WHILEING BUFFERINGREASON和AVPLAYERWAITINGTOMINIMIZESTALLS ASON


如果此属性的值为零,则表示当前播放器正在播放某些内容。

这与AVPlayer无关。如果媒体播放器本身为零,
self.mediaPlayer?.play()。代码行刚刚中止。那么它怎么可能产生错误呢?Swift不是这样工作的。您可以观察avplayer@matt该问题已被编辑。
private func addObserverPlayerItem()
    {
        if let playerItem = self.player?.currentItem{
            playerItem.addObserver(self, forKeyPath: "playbackBufferEmpty", options: .new, context: nil)
            playerItem.addObserver(self, forKeyPath: "playbackLikelyToKeepUp", options: .new, context: nil)
            playerItem.addObserver(self, forKeyPath: "playbackBufferFull", options: .new, context: nil)
            playerItem.addObserver(self, forKeyPath: "loadedTimeRanges", options: [.new], context: nil)
            self.player?.addObserver(self, forKeyPath: #keyPath(AVPlayer.currentItem.status), options: [.new, .initial], context: nil)
            self.player?.addObserver(self, forKeyPath: #keyPath(AVPlayer.status), options: [.new, .initial], context: nil)
        }
    }

override public func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if object is AVPlayerItem {
            switch keyPath {

            case "loadedTimeRanges":

                let duration = self.currentItem?.totalBuffer() ?? 0
                let totalduration = currentItem?.asset.duration
                self.videoControll?.slider.bufferEndValue = totalduration?.seconds ?? 0
                self.videoControll?.slider.bufferStartValue = (duration) / (totalduration?.seconds ?? 1)
                print((duration) / (totalduration?.seconds ?? 1))

            case "playbackBufferEmpty":
                // Show loader
                self.activityIndicator?.startAnimating()

            case "playbackLikelyToKeepUp":
                // Hide loader
                self.activityIndicator?.stopAnimating()

            case "playbackBufferFull":
                // Hide loader
                self.activityIndicator?.stopAnimating()
            case #keyPath(AVPlayer.currentItem.status):

                let newStatus: AVPlayerItem.Status
                if let newStatusAsNumber = change?[NSKeyValueChangeKey.newKey] as? NSNumber {
                    newStatus = AVPlayerItem.Status(rawValue: newStatusAsNumber.intValue)!
                } else {
                    newStatus = .unknown
                }
                if newStatus == .failed {
                    NSLog("SA Detected Error: \(String(describing: self.player?.currentItem?.error?.localizedDescription)), error: \(String(describing: self.player?.currentItem?.error))")
                }
            case #keyPath(AVPlayer.status):
                print()
            case .none:
                self.activityIndicator?.stopAnimating()
            case .some(_):
                self.activityIndicator?.stopAnimating()
            }
        }
    }
private func addObserverPlayerItem()
    {
        if let playerItem = self.player?.currentItem{
            playerItem.addObserver(self, forKeyPath: "playbackBufferEmpty", options: .new, context: nil)
            playerItem.addObserver(self, forKeyPath: "playbackLikelyToKeepUp", options: .new, context: nil)
            playerItem.addObserver(self, forKeyPath: "playbackBufferFull", options: .new, context: nil)
            playerItem.addObserver(self, forKeyPath: "loadedTimeRanges", options: [.new], context: nil)
            self.player?.addObserver(self, forKeyPath: #keyPath(AVPlayer.currentItem.status), options: [.new, .initial], context: nil)
            self.player?.addObserver(self, forKeyPath: #keyPath(AVPlayer.status), options: [.new, .initial], context: nil)
        }
    }

override public func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if object is AVPlayerItem {
            switch keyPath {

            case "loadedTimeRanges":

                let duration = self.currentItem?.totalBuffer() ?? 0
                let totalduration = currentItem?.asset.duration
                self.videoControll?.slider.bufferEndValue = totalduration?.seconds ?? 0
                self.videoControll?.slider.bufferStartValue = (duration) / (totalduration?.seconds ?? 1)
                print((duration) / (totalduration?.seconds ?? 1))

            case "playbackBufferEmpty":
                // Show loader
                self.activityIndicator?.startAnimating()

            case "playbackLikelyToKeepUp":
                // Hide loader
                self.activityIndicator?.stopAnimating()

            case "playbackBufferFull":
                // Hide loader
                self.activityIndicator?.stopAnimating()
            case #keyPath(AVPlayer.currentItem.status):

                let newStatus: AVPlayerItem.Status
                if let newStatusAsNumber = change?[NSKeyValueChangeKey.newKey] as? NSNumber {
                    newStatus = AVPlayerItem.Status(rawValue: newStatusAsNumber.intValue)!
                } else {
                    newStatus = .unknown
                }
                if newStatus == .failed {
                    NSLog("SA Detected Error: \(String(describing: self.player?.currentItem?.error?.localizedDescription)), error: \(String(describing: self.player?.currentItem?.error))")
                }
            case #keyPath(AVPlayer.status):
                print()
            case .none:
                self.activityIndicator?.stopAnimating()
            case .some(_):
                self.activityIndicator?.stopAnimating()
            }
        }
    }