iOS 6 shouldAutorotate: is NOT being called
Solution 1
See if you are getting the following error when your App starts.
Application windows are expected to have a root view controller at the end of application launch
If so the way to fix it is by making the following change in the AppDelegate.m
file (although there seem to be a number of answers how to fix this):
// Replace
[self.window addSubview:[navigationController view]]; //OLD
// With
[self.window setRootViewController:navigationController]; //NEW
After this shouldAutoRotate
should be correctly called.
Solution 2
When using UINavigationController as the basis for an app I use the following subclass to give me the flexibility to allow the top most child viewcontroller to decide about rotation.
@interface RotationAwareNavigationController : UINavigationController
@end
@implementation RotationAwareNavigationController
-(NSUInteger)supportedInterfaceOrientations {
UIViewController *top = self.topViewController;
return top.supportedInterfaceOrientations;
}
-(BOOL)shouldAutorotate {
UIViewController *top = self.topViewController;
return [top shouldAutorotate];
}
@end
Solution 3
That method is not the correct way to determine that. The correct method is willRotateToInterfaceOrientation:duration:
The should rotate to orientation (as opposed to shouldAutorotate) method is deprecated and will no longer be called as of iOS 6, but it was not meant to be used the way you were using it anyway.
EDIT Response to repeated downvotes. Please explain why using the method I indicated is not an (to quote OP) "indication that a rotation is about to occur." The content of the question and the title are mismatched.
Solution 4
It looks that on iOS 6 the container navigations controller doesn't consult child view controllers when rotating:
in iOS 6 release notes :
Now, iOS containers (such as UINavigationController) do not consult their children to determine whether they should autorotate. By default, an app and a view controller’s supported interface orientations are set to UIInterfaceOrientationMaskAll for the iPad idiom and UIInterfaceOrientationMaskAllButUpsideDown for the iPhone idiom.
This behavior is easy to test. What I did is to use the same custom view controller
- first case as a main view controller
- second case as a child of a UIPageViewController
In the first case everything is decided in the custom navigation controller by the combination of shouldAutorotate
and supportedInterfaceOrientations
given that supportedInterfaceOrientations
agrees with the supported orientations of the application.
In the second case even if the supportedInterfaceOrientations
of the custom view controller is called by the UIPageViewController the return value is not taken in to consideration. It works if the two methods are overwritten in a subclass of the UIPageViewController. I am not sure about the side effects of that as this class is not supposed to be subclassed.
Solution 5
If your viewController
is a child viewController
in a UINavigationController
then you can do the following:
- Subclass
UINavigationController
- override
shouldAutoRotate
in your subclass - send your
topViewController
this message when this method get called
// This Method is inside your UINavigationController
subclass
- (BOOL)shouldAutorotate
{
if([self.topViewController respondsToSelector:@selector(shouldAutorotate)])
{
return [self.topViewController shouldAutorotate];
}
return NO;
}
- Now your viewControllers will respond respectively to this method.
- Note, that you can do the same with other orinetaion-methods
Related videos on Youtube
Lizza
Updated on April 24, 2020Comments
-
Lizza about 4 years
I have been scouring the internet for a solution to this but am finding nothing. I am trying to make my iOS 5 app iOS 6 compatible. I cannot get the orientation stuff to work right. I am unable to detect when a rotation is about to happen. Here is the code I am trying:
- (BOOL)shouldAutorotate { return NO; } - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; } // pre-iOS 6 support - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { return (toInterfaceOrientation == UIInterfaceOrientationPortrait); }
The new supportedInterfaceOrientation: method gets called just fine. The shouldAutorotate method, however, will not fire. I need to do some image swapping on rotate, but I can't get any indication that a rotation is about to occur.
Thanks in advance.
-
KarenAnne over 11 yearsThis is answered in here: stackoverflow.com/questions/12260261/… See it :D
-
Daniel J over 8 years@KarenAnne, that answer doesn't fix the issue of 'shouldAutorotate' not being called in the first place. Also, 'shouldAutorotateToInterfaceOrientation' is deprecated in iOS 6, so it shouldn't be considered a valid option going foward.
-
-
Daniel Wood over 11 years-(BOOL)shouldRotate has appeared in iOS 6, however, it is never called. How is one meant to have a view controller that rotates only some of the time now (for instance having a lock button to protect against rotations)?
-
Daniel Wood over 11 yearsI figured out why my shouldAutorotate was not getting called in iOS 6. It was due to my view controller being a child of a UINavigationController and it appears that the nav controller doesn't delegate the -shouldAutorotate method to it's topViewController like the previous behaviour. You can get around this by subclassing the UINavigationController and overriding the -shouldAutorotate and -supportedIntervalOrientations methods.
-
borrrden over 11 yearsYeah, it's a new way of doing things...only presented and root view controllers get the calls. The reasoning is that child view controllers usually just resize to fit the frames of their parents anyway. However, the wilRotate and didRotate methods are forwarded to child controllers by default.
-
possen over 11 yearsSubclassing UINavigationController is not recommended. A category is better see stackoverflow.com/questions/12520030/…
-
borrrden over 11 years@possen Out of curiousity, why do you say that? To me it seems like a category would be a stranger choice since it will delete an existing implementation and make it unreachable (compiler warning will be produced)
-
Mike M over 11 yearsThere's a thread on the Apple forums where the Apple rep explicitly recommends against making a category, but subclassing instead. devforums.apple.com/message/744384
-
Dejell over 11 yearsWEll it doesn't work for me for UIImagePickerController. I tried to extend it (as it extends UINavigationController) and implement the method supportedIntervalOrientation and shouldAutoRotate but it wouldn't help
-
yoninja over 11 yearsI think this should be accepted as the correct answer. I had the same problem before but was able to fix it by doing something like this: self.window.rootViewController = navigationController; (which is the same as @user1672376's answer)
-
ashish about 11 yearsyes I was trying hard to get shouldAutoRotate method to call but it was not working as soon as I changed the above piece of code it worked perfectly. This is the correct answer I was searching it lot.
-
Guilherme Torres Castro about 11 yearsThis answer is completely wrong, shouldAutorate is not deprecated, In fact it's only available on IOS 6.0 and it's the correct way to determine if the screen should or not rotate. the willRotateToInterfaceOrientation:duration: yes called when the screen will be rotate, not do determine if should or not rotate.
-
borrrden about 11 yearsThis answer looks like it has been edited since I answered...I believe before it only had the old version of shouldRotate (shouldAutorotateToInterfaceOrientation). But my answer is still not "completely wrong" because OP is looking for (in his words) "detect when a rotation is about to happen". That is exactly what the willRotate method is for.
-
iEngineer about 11 yearsGreat.. it saved my time.. ;-)
-
Mausimo about 11 yearsSolved my issue also. IMO this answer should be selected.
-
Bill Cheswick almost 11 yearsNo, viewDIDLoad is too early: the VC doesn't know about its views yet. Do it in viewWillAppear, when self.view knows its current frame.
-
rudifa over 10 yearsSpot on, your answer saved my day.
-
Gallonallen over 10 yearsThis is by far the easiest and most elegant solution to allowing each ViewController in a NavigationController to have their own supported interface orientations.
-
vincentjames501 about 10 yearsThis is indeed a great solution and can be used with SplitViewControllers as well with a little tweaking.
-
Devang Vyas about 10 yearssave my day (and night too)...Thanks!
-
tedyyu almost 10 yearsTo be more clear, create such a sub-class and then set it as the custom class for your navigation controller in storyboard Identity Inspector.
-
Daniel J over 8 yearsBut if you're not getting that error, and neither do you want to set some random UIViewController as the root view controller...
-
Patrick Domegan over 7 yearsGreat answer thanks! Return type of supportedInterfaceOrientations should be changed from NSUInteger to UIInterfaceOrientationMask to remove a warning.
-
Patrick Domegan over 7 yearsNote: for this to work on iPad, you need to opt out of multitasking: <stackoverflow.com/a/31771093/341994>