10
votes

My iPhone app is a portrait orientation only app and in my app I have a UITableView that has a UIWebView in the first UITableCell. The UIWebView shows an embedded youtube video. When I click on the video to play it enters fullscreen mode. What I need to do is, allow the user to rotate their device and play the video in landscape mode. Then when the video is stopped only allow portrait again. I setup to listen for the notification when the video enters fullscreen and leaves full screen. But I don't know how to programmatically allow the user to rotate the interface orientation.

so basically I have 2 methods called when the notification is passed

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(youTubeStarted:) name:@"UIMoviePlayerControllerDidEnterFullscreenNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(youTubeFinished:) name:@"UIMoviePlayerControllerDidExitFullscreenNotification" object:nil];

-(void)youTubeStarted:(NSNotification *)notification{
    // Entered fullscreen code goes here.
}

-(void)youTubeFinished:(NSNotification *)notification{
    // Left fullscreen code goes here.
}

What would I put in those 2 methods to allow orientation change only during the video playback?

3
Be careful, since IOS6 the notification for the 'video done button' seem to be : UIMoviePlayerControllerWillExitFullscreenNotification (see: stackoverflow.com/a/8554040/1436861 and stackoverflow.com/a/12681507/1436861) - Thomas Besnehard

3 Answers

19
votes

I figured it out. In my 2 methods:

-(void)youTubeStarted:(NSNotification *)notification{
   // Entered Fullscreen code goes here..
   AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
   appDelegate.fullScreenVideoIsPlaying = YES;
}

-(void)youTubeFinished:(NSNotification *)notification{
   // Left fullscreen code goes here...
   AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
   appDelegate.fullScreenVideoIsPlaying = NO;

   //CODE BELOW FORCES APP BACK TO PORTRAIT ORIENTATION ONCE YOU LEAVE VIDEO.
   [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
    //present/dismiss viewcontroller in order to activate rotating.
    UIViewController *mVC = [[UIViewController alloc] init];
    [self presentModalViewController:mVC animated:NO];
    [self dismissModalViewControllerAnimated:NO];
}

I accessed my App delegate in the above methods by setting the BOOL property of my AppDelegate. Then I called the application method below in my AppDelegate.m:

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskPortrait;
if (self.fullScreenVideoIsPlaying == YES) {
    return UIInterfaceOrientationMaskAllButUpsideDown;
}
else {
    if(self.window.rootViewController){
        UIViewController *presentedViewController = [[(UINavigationController  *)self.window.rootViewController viewControllers] lastObject];
        orientations = [presentedViewController supportedInterfaceOrientations];

    }
    return orientations;
}
}

The self.fullScreenVideoIsPlaying is a BOOL that I set as a property in my AppDelegate.h file.

I hope this helps others the 5 hours I lost figuring it out.

2
votes

If you only want to support landscape playback in fullscreen. From iOS 8 onwards, video from UIWebView plays inside AVPlayerViewController.

In your AppDelegate check if presenting window contains AVPlayerViewController.

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {

    if let w = window, let root = w.rootViewController {

        if root.childViewControllers.first is AVPlayerViewController {  
            return UIInterfaceOrientationMask.allButUpsideDown
        }
    }

    return UIInterfaceOrientationMask.portrait
}
0
votes

You would have a global state variable, probably in your app delegate or wherever you store your variables that should be globally accessible, and then set it to true or false depending on wether the movie player is in fullscreen or not. In the callbacks that are called to rotate the app, you check the state of the variable and depending on that return if the rotation is allowed or not.