Search code examples
swiftavfoundationswift4avplayerkey-value-observing

Swift 4 switch to new observe API


I am having trouble with the new observe API in Swift 4.

player = AVPlayer()
player?.observe(\.currentItem.status, options: [.new], changeHandler: { [weak self] (player, newValue) in
    if let status = AVPlayer.Status(rawValue: (newValue as! NSNumber).intValue) {

   }
 }

But I get an error

Type of expression is ambiguous without more context.

How do I fix it? Not sure about keyPath syntax.

There is also a warning in extracting AVPlayerStatus in the closure above

Cast from 'NSKeyValueObservedChange' to unrelated type 'NSNumber' always fails"


Solution

  • currentItem is an optional property of AVPlayer. The following compiles in Swift 4.2/Xcode 10 (note the additional question mark in the key path):

    let observer = player.observe(\.currentItem?.status, options: [.new]) {
        (player, change) in
        guard let optStatus = change.newValue else {
            return // No new value provided by observer
        }
        if let status = optStatus {
            // `status` is the new status, type is `AVPlayerItem.Status`
        } else {
            // New status is `nil`
        }
    }
    

    The observed property is an optional AVPlayer.Status?, therefore change.newValue inside the callback is a “double optional” AVPlayer.Status?? and must be unwrapped twice.

    It may fail to compile in older Swift versions, compare Swift’s ‘observe()’ doesn’t work for key paths with optionals? in the Swift forum.