1

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.

Community
  • 1
  • 1
Don Miguel
  • 882
  • 9
  • 19
  • is ur viewcontroller visible ? – Kunal Balani Dec 06 '13 at 15:38
  • willAnimateRotationToInterfaceOrientation: method is no longer called for invisible view controllers. So if your view controller presents another which takes over, only the other one will hear these notifications. – Kunal Balani Dec 06 '13 at 15:39
  • The rootViewController is not visible. Even though I have noticed that only the rootViewController gets notified of changes in orientation, its `willAnimateRotationToInterfaceOrientation` never gets called. – Don Miguel Dec 06 '13 at 16:25

3 Answers3

3

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]));
    }
}
Giuseppe Garassino
  • 2,272
  • 1
  • 27
  • 47
  • Could you explain the way in which willAnimateRotationToInterfaceOrientation is being called has changed? I have added the methods you have proposed in my rootController, but they are still not being called. – Don Miguel Dec 06 '13 at 15:31
  • These methods should be called... Let me think... I had some problems in the past moving projects from old to new versions. Is your main.m file like the one I wrote in my EDIT? – Giuseppe Garassino Dec 06 '13 at 23:25
  • My main.m did not look like your edit. I did update it with the changes you have proposed, but with no real effect. Thanks anyway. – Don Miguel Dec 07 '13 at 11:59
2

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.

Don Miguel
  • 882
  • 9
  • 19
0

Implement this method, return YES for what you need.

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation

Aura
  • 246
  • 1
  • 10