Swift 中 "func observeValueForKeyPath(keyPath : NSString, object : AnyObject, change : NSDictionary, context : Void)" 的问题
Issue with "func observeValueForKeyPath(keyPath : NSString, object : AnyObject, change : NSDictionary, context : Void)" in Swift
我已经为这样的 AVPlayer 添加了一个观察者
self.audioPlayer.addObserver(self, forKeyPath: "currentItem.status", options: [NSKeyValueObservingOptions.New, NSKeyValueObservingOptions.Initial], context: nil)
并打电话给
func observeValueForKeyPath(keyPath : NSString, object : AnyObject, change : NSDictionary, context : Void) {
if object as! AVPlayer == self.audioPlayer && keyPath.isEqualToString("currentItem.status")
{
let playerStatus = self.audioPlayer.currentItem!.status.rawValue as Int
if playerStatus == AVPlayerStatus.Failed.rawValue
{
self.replaceCurrentItem(self.fileName)
}
else if playerStatus == AVPlayerStatus.ReadyToPlay.rawValue
{
self.playAudio()
self.updateDurationPeriodcally()
self.updateInfo()
}
else if playerStatus == AVPlayerStatus.Unknown.rawValue
{
print("\(self.audioPlayer.currentItem!.error)")
}
}
}
问题是 observeValueForKeyPath
从未被调用过。
完整代码
func loadPlayer (urlString : NSString)
{
let url : NSURL = NSURL(string: urlString as String)!
let length = (url.absoluteString).characters.count as Int
if length == 0
{
return
}
let asset = AVURLAsset(URL: url, options: nil)
let anItem = AVPlayerItem(asset: asset)
self.audioPlayer = AVPlayer(playerItem: anItem)
self.audioPlayer.volume = 1.0
self.audioPlayer.play()
addObserver(self,
forKeyPath: ObservatingKeyPath,
options: NSKeyValueObservingOptions.New,
context: PlayerStatusObservingContext)
self.audioPlayer.addObserver(self, forKeyPath: "currentItem.status", options: [NSKeyValueObservingOptions.New, NSKeyValueObservingOptions.Initial], context: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "itemDidFinishPlaying:", name:AVPlayerItemDidPlayToEndTimeNotification, object: nil)
}
你是怎么观察玩家物品的。可能是您观察不正确。下面用一个简单的例子来说明如何正确观察AVPlayer的状态,
class TestViewController: UIViewController
{
private var player: AVPlayer!
private var playingIndex = 0
private var songs = ["UpTown.mp3", "TurnMeOn.mp3"]
private let ObservatingKeyPath = "currentItem.status"
private let PlayerStatusObservingContext = UnsafeMutablePointer<Int>(bitPattern: 1)
override func viewDidLoad()
{
super.viewDidLoad()
createPlayer()
setupGestures()
playNext()
}
func createPlayer()
{
player = AVPlayer()
player.addObserver(self,
forKeyPath: ObservatingKeyPath,
options: NSKeyValueObservingOptions.New,
context: PlayerStatusObservingContext)
}
func setupGestures()
{
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "playNext")
view.addGestureRecognizer(tapGestureRecognizer)
}
func playNext()
{
let url = NSBundle.mainBundle().URLForResource(songs[playingIndex], withExtension: nil)
let playerItem = AVPlayerItem(URL: url!)
player.replaceCurrentItemWithPlayerItem(playerItem)
player.play()
playingIndex = (++playingIndex % 2)
}
override func observeValueForKeyPath(keyPath: String?,
ofObject object: AnyObject?,
change: [NSObject : AnyObject]?,
context: UnsafeMutablePointer<Void>)
{
if context == PlayerStatusObservingContext
{
if let change = change as? [String: Int]
{
let newChange = change[NSKeyValueChangeNewKey]!
switch newChange
{
case AVPlayerItemStatus.ReadyToPlay.rawValue:
print("Ready to play")
case AVPlayerItemStatus.Unknown.rawValue:
print("Unknown")
default:
print("Other status")
}
}
return
}
super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
}
}
并在开始或更改歌曲时打印出以下内容,
Unknown
Ready to play
我已经为这样的 AVPlayer 添加了一个观察者
self.audioPlayer.addObserver(self, forKeyPath: "currentItem.status", options: [NSKeyValueObservingOptions.New, NSKeyValueObservingOptions.Initial], context: nil)
并打电话给
func observeValueForKeyPath(keyPath : NSString, object : AnyObject, change : NSDictionary, context : Void) {
if object as! AVPlayer == self.audioPlayer && keyPath.isEqualToString("currentItem.status")
{
let playerStatus = self.audioPlayer.currentItem!.status.rawValue as Int
if playerStatus == AVPlayerStatus.Failed.rawValue
{
self.replaceCurrentItem(self.fileName)
}
else if playerStatus == AVPlayerStatus.ReadyToPlay.rawValue
{
self.playAudio()
self.updateDurationPeriodcally()
self.updateInfo()
}
else if playerStatus == AVPlayerStatus.Unknown.rawValue
{
print("\(self.audioPlayer.currentItem!.error)")
}
}
}
问题是 observeValueForKeyPath
从未被调用过。
完整代码
func loadPlayer (urlString : NSString)
{
let url : NSURL = NSURL(string: urlString as String)!
let length = (url.absoluteString).characters.count as Int
if length == 0
{
return
}
let asset = AVURLAsset(URL: url, options: nil)
let anItem = AVPlayerItem(asset: asset)
self.audioPlayer = AVPlayer(playerItem: anItem)
self.audioPlayer.volume = 1.0
self.audioPlayer.play()
addObserver(self,
forKeyPath: ObservatingKeyPath,
options: NSKeyValueObservingOptions.New,
context: PlayerStatusObservingContext)
self.audioPlayer.addObserver(self, forKeyPath: "currentItem.status", options: [NSKeyValueObservingOptions.New, NSKeyValueObservingOptions.Initial], context: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "itemDidFinishPlaying:", name:AVPlayerItemDidPlayToEndTimeNotification, object: nil)
}
你是怎么观察玩家物品的。可能是您观察不正确。下面用一个简单的例子来说明如何正确观察AVPlayer的状态,
class TestViewController: UIViewController
{
private var player: AVPlayer!
private var playingIndex = 0
private var songs = ["UpTown.mp3", "TurnMeOn.mp3"]
private let ObservatingKeyPath = "currentItem.status"
private let PlayerStatusObservingContext = UnsafeMutablePointer<Int>(bitPattern: 1)
override func viewDidLoad()
{
super.viewDidLoad()
createPlayer()
setupGestures()
playNext()
}
func createPlayer()
{
player = AVPlayer()
player.addObserver(self,
forKeyPath: ObservatingKeyPath,
options: NSKeyValueObservingOptions.New,
context: PlayerStatusObservingContext)
}
func setupGestures()
{
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "playNext")
view.addGestureRecognizer(tapGestureRecognizer)
}
func playNext()
{
let url = NSBundle.mainBundle().URLForResource(songs[playingIndex], withExtension: nil)
let playerItem = AVPlayerItem(URL: url!)
player.replaceCurrentItemWithPlayerItem(playerItem)
player.play()
playingIndex = (++playingIndex % 2)
}
override func observeValueForKeyPath(keyPath: String?,
ofObject object: AnyObject?,
change: [NSObject : AnyObject]?,
context: UnsafeMutablePointer<Void>)
{
if context == PlayerStatusObservingContext
{
if let change = change as? [String: Int]
{
let newChange = change[NSKeyValueChangeNewKey]!
switch newChange
{
case AVPlayerItemStatus.ReadyToPlay.rawValue:
print("Ready to play")
case AVPlayerItemStatus.Unknown.rawValue:
print("Unknown")
default:
print("Other status")
}
}
return
}
super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
}
}
并在开始或更改歌曲时打印出以下内容,
Unknown
Ready to play