简体   繁体   中英

How to detect the toggle on the display of playback controls with AVPlayerViewController?

I'd like to know if it is possible to detect when the playback controls appear or disappear from the AVPlayerViewController view. I'm trying to add a UI element on my player that must follow the playback controls display. Appearing only when the controls are displayed, disappearing otherwise

I don't seem to find any value that I can observe on AVPlayerViewController to achieve this nor any callbacks or delegate methods.

My project is in Swift.

A simple way to observe and respond to the playback changes is to use key-value observing (KVO) . In your case, observe AVPlayer's timeControlStatus or rate property.

eg:

{
  // 1. Setup AVPlayerViewController instance (playerViewController)

  // 2. Setup AVPlayer instance & assign it to playerViewController

  // 3. Register self as an observer of the player's `timeControlStatus` property

  // 3.1. Objectice-C
  [player addObserver:self
           forKeyPath:@"timeControlStatus"
              options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew // NSKeyValueObservingOptionOld is optional here
              context:NULL];

  // 3.2. Swift
  player.addObserver(self,
                     forKeyPath: #keyPath(AVPlayer.timeControlStatus),
                     options: [.old, .new], // .old is optional here
                     context: NULL)
}

To be notified of state changes, you implement the -observeValueForKeyPath:ofObject:change:context: method. This method is invoked whenever the timeControlStatus value changes.

// Objective-C
- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary <NSKeyValueChangeKey, id> *)change
                       context:(void *)context
{
  if ([keyPath isEqualToString:@"timeControlStatus"]) {
    // Update your custom UI here depend on the value of `change[NSKeyValueChangeNewKey]`:
    // - AVPlayerTimeControlStatusPaused
    // - AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate
    // - AVPlayerTimeControlStatusPlaying
    AVPlayerTimeControlStatus timeControlStatus = (AVPlayerTimeControlStatus)[change[NSKeyValueChangeNewKey] integerValue];
    // ...

  } else {
    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
  }
}

// Swift
override func observeValue(forKeyPath keyPath: String?,
                           of object: Any?,
                           change: [NSKeyValueChangeKey : Any]?,
                           context: UnsafeMutableRawPointer?)
{
  if keyPath == #keyPath(AVPlayer.timeControlStatus) {
    // Deal w/ `change?[.newKey]`
  } else {
    super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
  }
}

And last most important step , remember to remove the observer when you don't need it anymore, generally at -dealloc :

[playerViewController.player removeObserver:self forKeyPath:@"timeControlStatus"];

Btw, you can also observe AVPlayer's rate property, cause -play equivalents to setting the value of rate to 1.0, and -pause equivalent to setting the value of rate to 0.0.

But in your case, I think timeControlStatus makes more sense.


There's an official DOC for further reading (but just "Ready to Play", "Failed" & "Unknown" states, useless here): "Responding to Playback State Changes" .

Hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM