I have an app where users can open videos from UIWebview, including Youtube ones. In iOS7, I was able to get a notification when it started playing, or when it became full screen, which is vital for me to show certain options to the user and modify the interface.
I used to use this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(VideoExitFullScreen:) name:@"UIMoviePlayerControllerDidExitFullscreenNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(VideoEnterFullScreen:) name:@"UIMoviePlayerControllerDidEnterFullscreenNotification" object:nil];
However, since iOS8, I can't achieve this. It is like the notification is no longer triggered from UIWebview videos. However, it is still triggered from normal videos, non-Webview, as I've tested.
Any idea of what have changed?
This is the work around I found for this..
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(VideoExitFullScreen:)
name:UIWindowDidBecomeVisibleNotification
object:self.view.window];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(VideoEnterFullScreen:)
name:UIWindowDidBecomeHiddenNotification
object:self.view.window];
Swift 5.1:
NotificationCenter.default.addObserver(
forName: UIWindow.didResignKeyNotification,
object: self.view.window,
queue: nil
) { notification in
print("Video is now fullscreen")
}
NotificationCenter.default.addObserver(
forName: UIWindow.didBecomeKeyNotification,
object: self.view.window,
queue: nil
) { notification in
print("Video stopped")
}
update for Swift 4.2, iOS 12.1 and WKWebView:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// listen for videos playing in fullscreen
NotificationCenter.default.addObserver(self, selector: #selector(onDidEnterFullscreen(_:)), name: UIWindow.didBecomeVisibleNotification, object: view.window)
// listen for videos stopping to play in fullscreen
NotificationCenter.default.addObserver(self, selector: #selector(onDidLeaveFullscreen(_:)), name: UIWindow.didBecomeHiddenNotification, object: view.window)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// remove video listeners
NotificationCenter.default.removeObserver(self, name: UIWindow.didBecomeVisibleNotification, object: view.window)
NotificationCenter.default.removeObserver(self, name: UIWindow.didBecomeHiddenNotification, object: view.window)
}
@objc func onDidEnterFullscreen(_ notification: Notification) {
print("video is now playing in fullscreen")
}
@objc func onDidLeaveFullscreen(_ notification: Notification) {
print("video has stopped playing in fullscreen")
}
@NorthBlast's answer works well for detecting any UIWindow
appearing on top of the UIViewController
that holds the UIWebView
. Unfortunately, it's hard to filter what kind of UIWindow
is (since, well... you can't really know if it is a video or some other kind of window).
There are 3 special cases I prefer to filter, in which you're sure they are NOT video player windows, those are:
1) _UIAlertControllerShimPresenterWindow
, which is a kind of window that appears when using alerts (like UIAlertView
).
2) UITextEffectsWindow
, which appears when presenting special iOS windows (like the share window, UIActivityViewController
).
3) UIRemoteKeyboardWindow
which appears when presenting the keyboard (for some reason, this class only appeared to me when using Swift, but on Objective-C it didn't... no clue why is that).
So to subscribe to notifications, I use (just like @NorthBlast said):
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(windowDidBecomeActive:)
name:UIWindowDidBecomeVisibleNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(windowDidBecomeHidden:)
name:UIWindowDidBecomeHiddenNotification
object:nil];
Then the implementations:
- (void)windowDidBecomeActive:(NSNotification *)notification {
if ( [self isVideoPlayerWindow:notification.object] ) {
// Do what's needed if it is a video
// For example, on a live streaming radio app, I would stop the audio if a video is started
}
}
- (void)windowDidBecomeHidden:(NSNotification *)notification {
if ( [self isVideoPlayerWindow:notification.object] ) {
// Do what's needed if it is a video
}
}
- (BOOL)isVideoPlayerWindow:(id)notificationObject {
/*
Define non video classes here, add more if you need it
*/
static NSArray *nonVideoClasses = @[
@"_UIAlertControllerShimPresenterWindow",
@"UITextEffectsWindow",
@"UIRemoteKeyboardWindow"
];
BOOL isVideo = YES;
for ( NSString *testClass in nonVideoClasses ) {
isVideo = isVideo && ! [notificationObject isKindOfClass:NSClassFromString(testClass)];
}
return isVideo;
}
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