2

So, I've given up on trying to solve an issue I've been having where my controller will rotate without calling my shouldAutorotateToInterfaceOrientation: method, because everyone for a few years has been stating it as an iOS bug.

Now I need to just force rotate my UIViewController. Is there a way I can do that, since the UIDevice instance method has been removed now and I don't know what to do to force rotate my controller.

RileyE
  • 10,874
  • 13
  • 63
  • 106
  • Take a look at this question http://stackoverflow.com/questions/9826920/uinavigationcontroller-force-rotate. I am not sure, `+ (void)attemptRotationToDeviceOrientation` method can be the answer to your question. – Sierra Alpha Jul 06 '12 at 18:56
  • 1
    Its a good thing to know about, but unfortunately, my issue is the opposite. I'm not trying to rotate to a certain orientation, but back from a wrong orientation while the device is still being held in that incorrect orientation. – RileyE Jul 06 '12 at 20:16
  • You say that `shouldAutoRotateToInterfaceOrientation` isn't getting called. Clearly this is a pre-iOS6 issue, so maybe you don't care any more, but if you're still having this problem, this can be caused by allowing your view controller hierarchy to get out of sync with your view hierarchy (e.g. by incorrectly using `addSubview` to transitioning between views). If you're still having an issue here, feel free to let us know. – Rob Feb 01 '13 at 18:37
  • @Rob I am still having the issue. The issue is when the MPMediaPlayer shows up and is rotated to landscape (which is in a view that is portrait only - however I appreciate it rotating to landscape). When the MPMediaPlayer is dismissed, the `UIView` / `UIViewController` that presented it is now rotated to landscape without even calling any rotate methods. I can intercept rotation notifications with the `NSNotificationCenter`, but that won't help me, since I can't force rotate the controller. – RileyE Feb 01 '13 at 19:05

2 Answers2

7

I'm not sure which UIDevice method that you are saying has been removed, but the following has worked for me (this does use the UIDevice orientation method). Bottom line, if you have a view that only accepts landscape, you can use the following to force iOS to change the orientation. It's curious, but it works. I apologize that I can't give credit to the original author, but once came across this elsewhere on StackOverflow:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}

- (void)forceLandscape
{
    // make sure shouldAutorotateToInterfaceOrientation is configured to accept only landscape

    if (UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation]))
    {
        UIWindow *window = [[UIApplication sharedApplication] keyWindow];
        UIView *view = [window.subviews objectAtIndex:0];
        [view removeFromSuperview];
        [window addSubview:view];
    }
}

The equivalent to force portrait mode (assuming, of course, your shouldAutorotateToInterfaceOrientation accepts only portrait):

- (void)forcePortrait
{
    // make sure shouldAutorotateToInterfaceOrientation is configured to accept only portrait

    if (UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation]))
    {
        UIWindow *window = [[UIApplication sharedApplication] keyWindow];
        UIView *view = [window.subviews objectAtIndex:0];
        [view removeFromSuperview];
        [window addSubview:view];
    }
}
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • So, basically, remove the root view controller and readd it? Doesn't this seem a bit hackish, since the controller shouldn't be rotating anyways? Will apple allow this in a full application? – RileyE Jul 06 '12 at 20:10
  • I just want to wait to see if someone else has another option, but I'm pretty sure this is what I'll end up having to go with. – RileyE Jul 06 '12 at 20:11
  • Oh. Sorry. Its the root view, not view controller. I'm not reading things correctly! – RileyE Jul 06 '12 at 20:18
  • But I did try this and its still not forcing the rotation. – RileyE Jul 06 '12 at 20:20
  • @RileyE Yes, definitely hackish. Ugly, ugly, ugly. I don't like it, but it works for me. In answer to your question of it not working, I have to ask how you are creating your view. I only ask because if you're doing the `[self.view addSubview:controller.view]` that an alarming number of people use, that is well known to prevent scroll events from being sent to your new view. But if you're getting to your view via standard `pushViewController` or `presentViewController`, you should be ok. How are you transitioning to your landscape-only view? – Rob Jul 06 '12 at 20:29
  • Sorry. I am not being very clear. Everything is Portait only (at least for now) in all of the UIViewControllers and the plist. The media player that loads in a UIWebView in one of my UIViewControllers, however, can rotate for some odd reason and when it is dismissed, my UIViewController containing the UIWebView is now rotated to an unsupported orientation. And I am using pushViewController for adding that last UIViewController with the UIWebView to the UINavigationController's viewController stack. – RileyE Jul 06 '12 at 21:01
  • @RileyE I would have thought that you could add `[self forcePortrait]` in the `viewWillAppear`. I'll take a look. – Rob Jul 06 '12 at 21:17
  • viewWillAppear isn't called when the media player is dismissed, so I've added an observer, @"UIMoviePlayerControllerWillExitFullscreenNotification", that is called when the media player will be dismissed. It calls just fine, but it doesn't rotate the view. It is executing the code okay as well. I've tested with logs. – RileyE Jul 06 '12 at 21:24
0

Using xcode7.3 ios9. I have been trying to force landscape view on and off for over a week now, no hair left :(. For anyone else finding this question and none of the answers work, or any of the other myriad answers on forcing landscape, I finally found something that works here: http://www.btday.com/how-to-force-view-controller-orientation-in-ios-8/

Suggestion is to put operation in viewDidAppear, but it also seems to work in viewWillAppear and is slightly less ugly.

override func viewWillAppear(animated: Bool) {
    UIDevice.currentDevice().setValue(UIInterfaceOrientation.LandscapeLeft.rawValue, forKey: "orientation")
}

If this is wrong/bad, please speak up, only had a mac for a little over a month so I'm a total nuub!

Also note I'm using a UITabBarController and it doesn't seem to matter whether you put this in the tab bar controller or one of it's children

nikrb
  • 153
  • 3
  • 10