I’m currently working on an app for a client where certain features are disabled when a
video starts to play. Specifically, a video that’s embedded in a WKWebView.
One way of doing this would be to inject Javascript into the page like
I’ve written
about before and let that attach
listeners to every <video> tag on the page. When a video changes its play state our
listener could post a message to the app via
webkit.messageHandlers[_HANDLER_].postMessage(_OBJECT_); and we would need a handler in
the app to do whatever it is we want it to do.
That's a little messy.
When a video starts to play in a WKWebView the <video> is replaced by the native video
player. However, within the app we can’t get a reference to this video component in order to
query its playing state, so I wondered if maybe this might just fire an NSNotification we
could listen for.
I couldn’t find any documentation for this so I decided to listen for all notifications and see if I could find one that would do the trick.
To do that I added a notification center observer with no specific name, which translates to give me ALL of the notifications:
[[NSNotificationCenter defaultCenter] addObserverForName:nil
object:nil
queue:nil
usingBlock:^(NSNotification* notification) {
NSLog(@"Notification:\n"\
"name: %@\n"\
"object: %@\n"\
"userInfo: %@",
notification.name,
notification.object,
notification.userInfo);
}];
Clearing the console before tapping play on the video led me to find that there actually is
a notification that gets fired from the web view — its called SomeClientPlayingDidChange.
Inside the notification’s userInfo dictionary lies an IsPlaying key, with exactly what
we want.
This meant that now we could add an observer for this notification and a handler to do whatever it is we need to do:
// Listen for video playback
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(videoPlayingDidChange:)
name:@"SomeClientPlayingDidChange"
object:nil];
// Video playing state handler
- (void)videoPlayingDidChange:(NSNotification *)notification
{
BOOL isPlaying = [notification.userInfo[@"IsPlaying"] boolValue];
// Do stuff with this newfound knowledge
}
Caveats: this notification doesn’t appear to be documented and could change at any time. It probably will. At the time of writing this works on iOS 8.x/9.x - however since we’re simply listening to the notification, the app might lose this functionality but shouldn’t lead to any crashes.