Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS 6: How do I restrict some views to portrait and allow others to rotate?

I have an iPhone app that uses a UINavigationController to present a drill-down interface: First one view, then another, up to four levels deep. I want the first three views restricted to portrait orientation and only the last view should be allowed to rotate to landscape. When returning from the fourth view to the third and the fourth view was in landscape orientation I want everything to rotate back to portrait.

In iOS 5 I simply defined shouldAutorotateToInterfaceOrientation: in each of my view controllers to return YES for the allowable orientations. Everything worked as described above, including the return to portrait even if the device was being held in landscape orientation when returning from view controller #4 to #3.

In iOS 6 all view controllers rotate to landscape, breaking those that weren't meant to. The iOS 6 release notes say

More responsibility is moving to the app and the app delegate. Now, iOS containers (such as UINavigationController) do not consult their children to determine whether they should autorotate. [...] The system asks the top-most full-screen view controller (typically the root view controller) for its supported interface orientations whenever the device rotates or whenever a view controller is presented with the full-screen modal presentation style. Moreover, the supported orientations are retrieved only if this view controller returns YES from its shouldAutorotate method. [...] The system determines whether an orientation is supported by intersecting the value returned by the app’s supportedInterfaceOrientationsForWindow: method with the value returned by the supportedInterfaceOrientations method of the top-most full-screen controller.

So I subclassed UINavigationController, gave my MainNavigationController a boolean property landscapeOK and used this to return the allowable orientations in supportedInterfaceOrientations. Then in each of my view controllers' viewWillAppear: methods I have a line like this

    [(MainNavigationController*)[self navigationController] setLandscapeOK:YES]; 

to tell my MainNavigationController the desired behavior.

Here comes the question: If I now navigate to my fourth view in portrait mode and turn the phone over it rotates to landscape. Now I press the back button to return to my third view which is supposed to work portrait only. But it doesn't rotate back. How do I make it do that?

I tried

    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait] 

in the viewWillAppear method of my third view controller, but it doesn't do anything. Is this the wrong method to call or maybe the wrong place to call it or should I be implementing the whole thing in a totally different way?

like image 499
Harald Bögeholz Avatar asked Sep 27 '12 21:09

Harald Bögeholz


People also ask

How do you lock perspective on iPhone?

If you have an iPhone SE (2nd gen) or an iPhone 8 or earlier, swipe up from the bottom of your screen (3 finger swipe up for VoiceOver users), to open Control Center. Select the Portrait Orientation Lock icon. Your device's orientation will now stay locked in portrait mode until you turn Portrait Orientation Lock off.

Can you lock screen rotation on iPhone?

Lock or unlock the screen orientationYou can lock the screen orientation so that it doesn't change when you rotate iPhone. appears in the status bar (on supported models).

How do I force horizontal orientation in IOS?

On an iPhone with a Home button, swipe up from the bottom of the screen to access it. On an iPhone without a Home button, swipe down from the top-right corner of the screen instead. Here, tap on the rotation lock icon (which looks like a lock with a circular arrow) to turn it on or off.

How do I force portrait in IOS?

Swipe down from the top-right corner of your screen to open Control Center. Tap the Portrait Orientation Lock button to make sure that it's off.


2 Answers

I had the same problem and found a solution that works for me. To make it work, it is not sufficient to implement - (NSUInteger)supportedInterfaceOrientations in your UINavigationController. You also need to implement this method in your controller #3, which is the first one to be portrait-only after popping controller #4. So, I have the following code in my UINavigationController:

- (BOOL)shouldAutorotate {     return YES; }  - (NSUInteger)supportedInterfaceOrientations {     if (self.isLandscapeOK) {         // for iPhone, you could also return UIInterfaceOrientationMaskAllButUpsideDown         return UIInterfaceOrientationMaskAll;     }     return UIInterfaceOrientationMaskPortrait; } 

In view controller #3, add the following:

- (NSUInteger)supportedInterfaceOrientations {     return UIInterfaceOrientationMaskPortrait; } 

You don't need to add anything to your view controllers #1, #2, and #4. This works for me, I hope it will help you.

like image 163
Flo Avatar answered Oct 02 '22 11:10

Flo


Add a CustomNavigationController

Override these methods in it:

-(BOOL)shouldAutorotate {     return [[self.viewControllers lastObject] shouldAutorotate]; }  -(NSUInteger)supportedInterfaceOrientations {     return [[self.viewControllers lastObject] supportedInterfaceOrientations]; }  - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {     return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation]; } 

Now add all orientations in the plist

enter image description here

In the view controller add only the required ones:

-(BOOL)shouldAutorotate {     return YES; }  -(NSUInteger)supportedInterfaceOrientations {     return UIInterfaceOrientationMaskPortrait; } 

these methods override the navigation controller methods

like image 36
Zaraki Avatar answered Oct 02 '22 11:10

Zaraki