0

I need to observe the status of an AVPlayer, so I add an observer:

let player = AVPlayer(URL: NSURL(fileURLWithPath: tempFilePath))
player.addObserver(self, forKeyPath: "status", options: nil, context: nil)

And observe the change with the relevant function:

override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
    if object is AVPlayer {
        var player = object as! AVPlayer
        player.removeObserver(self, forKeyPath: "status")
    }
}

This is working fine, however, I need to some more information in the observeValueForKeyPath function, namely a dictionary:

var context = [
    "layer": CALayer(),
    "filePath": String()
]

Consequently, I figured I could pass that dictionary under the context parameter, since:

The context pointer can be used as a unique identifier to determine the change that is being observed, or to provide some other data to the observer (Source)

I'm not entirely sure how to pass the context variable, which has a [String, AnyObject] type as an UnsafeMutablePointer<Void> type.

Reading this, I figured I could do something like:

UnsafeMutablePointer(Unmanaged.passUnretained(context).toOpaque())
...
Unmanaged<[String, AnyObject]>.fromOpaque(COpaquePointer(context)).takeUnretainedValue()

But not surprisingly, that didn't work. I also figured I could pass the variable by reference, &context, but I was unable to decode the address of the original variable. Is this where NSCoder is used?

Community
  • 1
  • 1
Charlie
  • 11,380
  • 19
  • 83
  • 138
  • You are passing an *unretained* object pointer around, which works only if a reference to the context dictionary is held somewhere (otherwise it might have been destroyed when the callback method is called). Did you try it with a *retained* reference (as suggested in the linked answer)? – Martin R Sep 19 '15 at 18:07
  • @MartinR makes sense. I passed it as an `NSDictionary` (but not a `Dictionary`?) by using `UnsafeMutablePointer(Unmanaged.passRetained(context).toOpaque())`, and then reading it with, `Unmanaged.fromOpaque(COpaquePointer(context)).takeRetainedValue()`. Is this acceptable? Also, do I now need to release context? – Charlie Sep 19 '15 at 18:37
  • I think that is all explained in the answer to the linked question. passRetained increases the refcount and takeRetainedValue decreases it, so they must be properly balanced. – Martin R Sep 19 '15 at 19:27

0 Answers0