I'm trying to stream a video in my app. The method I've found is :
NSURL *theMovieURL = [NSURL URLWithString:self.data.trailer];
if (theMovieURL)
{
self.movieController = [[MPMoviePlayerViewController alloc] initWithContentURL:theMovieURL];
[self presentMoviePlayerViewControllerAnimated:self.movieController];
[self.movieController.moviePlayer play];
}
I'm not sure if it's the most conventional, but it works.
The problem is that I can't figure out how to allow the landscape mode, for the video only. Should I use something like shouldAutorotate
or shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
, and how ?
FYI, the entire app allows only the portrait mode.
Thanks for your help.
shouldAutoRotate
is deprecated as of iOS 6 and should be avoided unless you're going for < 6 .
Instead, you'd want to override the supportedInterfaceOrientations
and preferredInterfaceOrientationForPresentation
methods.
In this case, if you don't want to subclass the media player you could override a method in the app delegate like so:
- (NSUInteger) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if ([[self.window.rootViewController presentedViewController] isKindOfClass:[MPMoviePlayerViewController class]])
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
else
{
return UIInterfaceOrientationMaskPortrait;
}
}
@peko says correct way. when user exits from fullscreen video, this method called again with MPMoviePlayerViewController
class. you should check it is dismissed or not, if you don't, when user exit from video, main window will stay in landscape mode, and also you forgot MPInlineVideoFullscreenViewController
class. when you use embed player (not fullscreen) it is called with that class name.
I did it like that. it works for me.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)windowx
{
if ([[self.window.rootViewController presentedViewController] isKindOfClass:[MPMoviePlayerViewController class]] ||
[[self.window.rootViewController presentedViewController] isKindOfClass:NSClassFromString(@"MPInlineVideoFullscreenViewController")])
{
if ([self.window.rootViewController presentedViewController].isBeingDismissed)
{
return UIInterfaceOrientationMaskPortrait;
}
else
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
}
else
{
return UIInterfaceOrientationMaskPortrait;
}
}
The movie player might not be the first presented view controller, so you should do something like this
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
UIViewController* playerController = self.window.rootViewController.presentedViewController;
while (playerController && ![playerController isKindOfClass:[MPMoviePlayerViewController class]]) {
playerController = playerController.presentedViewController;
}
if (playerController && !playerController.isBeingDismissed) {
return UIInterfaceOrientationMaskAllButUpsideDown;
} else {
return UIInterfaceOrientationMaskPortrait;
}
}
Although MPMoviePlayerViewController
has been deprecated so you should use AVPlayerViewController
instead and check its class too in this loop.
The best way so far is to implement this AppDelegate function and check if the rootViewController
has a child of type AVPlayerViewController
or MPMoviePlayerViewController
then you return [.portrait, .landscapeLeft, .landscapeRight]
and else .portrait
.
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if let _ = UIApplication.shared.keyWindow?.rootViewController?.childViewControllers.first as? AVPlayerViewController {
return [.portrait, .landscapeLeft, .landscapeRight]
}
return .portrait
}
You should check on the keyWindow
of UIApplication
because apple presents this viewController in a another UIWindow
so if you try to do that check on the window that is declared in the AppDelegate
this won't work so be careful.