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.
e.g.:
{
// 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With