I have an old app, that still lives on iTunes, written in iOS 5. I would like to update it to run on ios 6 and 7. Everything has been fine so far, and I have updated my code to use ARC. However when trying to maintain the same autorotation philosophy I keep hitting a brick wall. I have already checked relative topics within SO like:
Forcing landscape and autorotate in iOS 7,
Autorotate in iOS 6 has strange behaviour
and following a similar topic I have found this:
iOS 6 Autorotation Problems and Help
which lead me to do the following:
I have set the rootViewController within my AppDelegate like so:
self.preloadingViewController = [[PreloadingViewController alloc] initWithNibName:@"PreloadingViewController" bundle:nil];
self.window.rootViewController = self.preloadingViewController;
I have placed:
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
within my AppDelegate. I have overriden shouldAutorotate
and supportedInterfaceOrientations
within the SuperViewController (parent in inheritance terms) of all of my app's UIViewControllers (including PreloadingViewController mentioned above):
- (BOOL)shouldAutorotate{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
and in every child UIViewController, I override
- (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
with code to layout ui elements in the desirable manner for portrait and landscape orientations.
Finally my app's plist file under
Supported interface orientations
contains:
Portrait (bottom home button), Landscape (left home button), Landscape (right home button)
all the orientations I want to support.
Still, even though supportedInterfaceOrientations
and shouldAutorotate
are being called for every orientation change on my rootViewController, willAnimateRotationToInterfaceOrientation
is never being called. I have even overriden shouldAutomaticallyForwardRotationMethods
in my SuperViewController to return YES, but to no avail.
What am I doing wrong here? Any ideas? I have even considered that the old ios5 - style xibs cause the issue but I do not think this is the case.
Thanks in advance.
In iOS 6 the way willAnimateRotationToInterfaceOrientation
is called changed.
Use:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
// Something
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
// Something
}
in your rootController
.
EDIT:
New main.m
#import <UIKit/UIKit.h>
#import "yourAppDelegate.h"
int main(int argc, char *argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([yourAppDelegate class]));
}
}
Since my rootViewController was the only one getting its shouldAutorotate
and supportedInterfaceOrientations
methods called, I decided to register every other view controller to get notified of any UIDeviceOrientationDidChangeNotification
.
[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
- (void)orientationChanged:(NSNotification *)notification
{
NSLog(@"Orientation changed!");
[self layoutForOrientation:[[UIDevice currentDevice] orientation]];
}
Within my layoutForOrientation:
method I handled the uiview's controls orientation.
However, although I did receive UIDeviceOrientationDidChangeNotification
notifications normally, my view orientation would not actually change to match the current orientation, i.e. if the new orientation was say, UIInterfaceOrientationLandscapeRight
, the view orientation would remain in UIInterfaceOrientationPortrait
and its children views would get rotated by 90 degrees. This did certainly not look right. After pulling a lot of hair out, I decided to abandon this route.
Instead, I have set my rootViewController to be a UINavigationController and have it push successive UIViewControllers on top of it. Since I did not want a navigation bar visible in my app I have set the navigation controller's navigationBarHidden
property set to YES. This way the method willAnimateRotationToInterfaceOrientation
is getting called on every UIViewController that is currently at the top of the navigationCotroller's stack of controllers, and its corresponding view and view controls rotate correctly for the desired orientations.
This works because most of my view controllers supported interface orientations match the mask: UIInterfaceOrientationMaskAllButUpsideDown
, the default behaviour for iPhone. Should I needed to support different orientations, I would have to subclass the UINavigationController and override supportedInterfaceOrientations
and shouldAutorotate
to enable the desired orientations support for the navigation stack's top view controller, as per Apple's example project: AlternateViews.
Implement this method, return YES for what you need.
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
来源:https://stackoverflow.com/questions/20425607/willanimaterotationtointerfaceorientation-not-called-on-ios6-7