目标:
我最终试图读取外部视频文件(.mp4,.mpg ...);在AVPlayerViewController的实例中。
但是我遇到了各种各样的KVO问题。
playerController.status playerController.contentDimensions playerController.playingOnExternalScreen playerController.externalPlaybackType playerController.allowsExternalPlayback playerController.hasEnabledVideo playerController.hasEnabledAudio bounds videoScaled playerController.playingOnExternalScreen view.viewWindowState绑定playerController.playing
self.playerItem!.addObserver(self,forKeyPath:“timedMetadata”, options:NSKeyValueObservingOptions.New,context:nil)
不起作用:
a)此观察者没有触发'observeValueForKeyPath()';和
b)我得到以下运行时错误(在立即删除观察者作为测试之后):
...原因:'无法移除观察者......关键路径 来自......的“timedMetadata”,因为它没有注册为观察者。'
class EditShowVideoViewController:AVPlayerViewController {
var playerItem:AVPlayerItem?
override func viewDidLoad() {
self.view.hidden = true
if let url = NSURL(string: gEditMediumTuple!.medium as! String) {
let asset = AVURLAsset(URL: url)
let requestedKeys = Array(arrayLiteral: "tracks", "playable")
asset.loadValuesAsynchronouslyForKeys(requestedKeys, completionHandler: { () in
// do something
dispatch_async(dispatch_get_main_queue(), {
self.playerItem = AVPlayerItem(asset: asset)
self.playerItem!.addObserver(self, forKeyPath: "timedMetadata", options: NSKeyValueObservingOptions.New, context: nil)
self.removeObserver(self, forKeyPath:"timedMetadata") //...still runtime error.
})
})
} else {
showAlert(sender: self.parentViewController!, withTitle: "No Video", withMessage: "No video is found.", alertPurpose: .noVideo)
}
}
override func observeValueForKeyPath(keyPath: String?,
ofObject object: AnyObject?, change: [String : AnyObject]?,
context: UnsafeMutablePointer<()>) {
print(keyPath!)
guard keyPath == "readyForDisplay" else {return}
guard let obj = object as? AVPlayerViewController else {return}
guard let ok = change?[NSKeyValueChangeNewKey] as? Bool else {return}
guard ok else {return}
dispatch_async(dispatch_get_main_queue(), {
self.finishConstructingInterface(obj)
})
self.removeObserver(self, forKeyPath:"timedMetadata")
}
func finishConstructingInterface (vc:AVPlayerViewController) {
self.removeObserver(self, forKeyPath:"readyForDisplay")
self.view.hidden = false
}
// ...
}
我想要做的就是加载视频网址并播放它。
如果缺乏补救措施,欢迎任何建议。
答案 0 :(得分:0)
运行时错误是因为您将观察结果添加到播放器项目,然后尝试将其从自己移除。
在观察者回调中,如果该键不属于您的观察,那么您应该调用super。如果不这样做,你不知道自己在打破什么。
考虑将视频VC添加为子项,而不是将您的类添加为子类。这将使其在逻辑上保持独立,并防止混淆KVO回调。
一般来说,使用KVO进行代码流管理会使您的代码更难以跟踪,调试和维护。最好使用不同的机制并将KVO纯粹保存为变更跟踪和响应。此外,至少保留一个布尔标志,表明您是否正在观察,以便您可以适当地整理。你不能让你的课程被解除分配并留下悬挂的观察。