4
votes

I have a table with a big list of stuff that comes from a plist file and clicking each of them takes you to a new view, a xib.

I have 2 views inside that .xib, one for portrait and one for landscape

In my h file I have this:

IBOutlet UIView *portraitView;  
IBOutlet UIView *landscapeView;

@property (nonatomic, retain) IBOutlet UIView *portraitView;  
@property (nonatomic, retain) IBOutlet UIView *landscapeView;

In my m file this:

[super viewDidLoad];  
    // Do any additional setup after loading the view from its nib.

    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:@"UIDeviceOrientationDidChangeNotification" object:nil];

}

- (void) orientationChanged:(id)object
{
    UIInterfaceOrientation interfaceOrientation = [[object object] orientation];

if (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)  
    {  
        self.view = self.portraitView;  
    }  
    else
    {  
        self.view = self.landscapeView;  
    }  
}

- (void)viewDidUnload
{

    [super viewDidUnload];  
    // Release any retained subviews of the main view.  
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation   
{  
    if (UIInterfaceOrientationIsPortrait(interfaceOrientation)) {  

       self.view = portraitView;
    } else if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {

       self.view = landscapeView;  
    }  
    return YES;

}

@end

Everything was working perfectly in iOS 5, showing landscape or portrait when needed.

Now with the iOS 6 update everything is a mess.

If I am in the table (portrait) view and click one item, it shows correct in portrait, if I rotate to landscape, the view shows the correct view as well, BUT being in landscape, if I go back to the table and select another item, it shows the portrait view instead of the landscape.

If I do the same but starting landscape, it shows portrait.

So, now the orientation is not working for anything.

The same happens to my other views using storyboard. They are portrait and always showed like that, now they rotate, shrink everything and leave my app as trash.

1- How can I fix the .xib orientation thing ?
2- How can I fix the storyboard orientation ? (they were static, now everything rotates (no code at all))

Thanks.

3

3 Answers

13
votes

I think that I have a work around. It's ugly but it's working... With iOS6 Apple suggest now to use 2 differences XIB file to switch between portrait & landscape view.

But if you want to use the previous method allowed in iOS 5.0 by "switching" between 2 UIView IBOutlet, you can try my ugly working solution. The idea is to rotate the view according to the orientation.

1) In you viewDidLoad, subscribe to orientation notification:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:@"UIDeviceOrientationDidChangeNotification" object:nil];
 }

2) Add a method called by the notification:

-(void)orientationChanged:(NSNotification *)object{
    NSLog(@"orientation change");
    UIDeviceOrientation deviceOrientation = [[object object] orientation];
    if(deviceOrientation == UIInterfaceOrientationPortrait || deviceOrientation == UIInterfaceOrientationPortraitUpsideDown){
        self.view = self.potraitView;
        if(deviceOrientation ==UIInterfaceOrientationPortraitUpsideDown){
            NSLog(@"Changed Orientation To PortraitUpsideDown");
            [self portraitUpsideDownOrientation];
        }else{
            NSLog(@"Changed Orientation To Portrait");
            [self portraitOrientation];
        }
    }else{
        self.view = self.landscapeView;
        if(deviceOrientation ==UIInterfaceOrientationLandscapeLeft){
            NSLog(@"Changed Orientation To Landscape left");
            [self landscapeLeftOrientation];
        }else{
            NSLog(@"Changed Orientation To Landscape right");
            [self landscapeRightOrientation];
        }

    }
}

3) And finally, add rotation method for each orientation:

-(void)landscapeLeftOrientation{

    // Rotates the view.
    CGAffineTransform transform = CGAffineTransformMakeRotation(-(3.14159/2));
    self.view.transform = transform;
    // Repositions and resizes the view.
    CGRect contentRect = CGRectMake(0, 0, 480, 320);
    self.view.bounds = contentRect;
}
-(void)landscapeRightOrientation{

    // Rotates the view.
    CGAffineTransform transform = CGAffineTransformMakeRotation(3.14159/2);
    self.view.transform = transform;
    // Repositions and resizes the view.
    CGRect contentRect = CGRectMake(0, 0, 480, 320);
    self.view.bounds = contentRect;
}
-(void)portraitOrientation{

    // Rotates the view.
    CGAffineTransform transform = CGAffineTransformMakeRotation(0);
    self.view.transform = transform;
    // Repositions and resizes the view.
    CGRect contentRect = CGRectMake(0, 0, 320, 480);
    self.view.bounds = contentRect;
}
-(void)portraitUpsideDownOrientation{

    // Rotates the view.
    CGAffineTransform transform = CGAffineTransformMakeRotation(3.14159);
    self.view.transform = transform;
    // Repositions and resizes the view.
    CGRect contentRect = CGRectMake(0, 0, 320, 480);
    self.view.bounds = contentRect;
}

I suggest you to make a custom UIViewController class and inherit-ate from this class to save redundant code. If you want to support both solution for ios5 and ios6 you can use a #endif macro to include the both code in your controllers.

Cheers

1
votes

No need to send and receive notifications:

In your appdelegate.m the following method

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window

is always called to check the window's orientation, so a simple way around is to have the below described code in your appdelegate.m

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{

    NSUInteger orientations = UIInterfaceOrientationMaskPortrait;

    if(self.window.rootViewController){
        UIViewController *presentedViewController ;
        if ([self.window.rootViewController isKindOfClass:([UINavigationController class])])
        {
            presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
        }
        else if ([self.window.rootViewController isKindOfClass:[UITabBarController class]]){
            UITabBarController *controller = (UITabBarController*)self.window.rootViewController;

            id selectedController =  [controller presentedViewController];

            if (!selectedController) {
                selectedController = [controller selectedViewController];
            }

                if ([selectedController isKindOfClass:([UINavigationController class])])
                {
                    presentedViewController = [[(UINavigationController *)selectedController viewControllers] lastObject];
                }
                else{
                    presentedViewController = selectedController;
                }
        }
        else
        {
            presentedViewController = self.window.rootViewController;
        }

        if ([presentedViewController respondsToSelector:@selector(supportedInterfaceOrientations)]) {
            orientations = [presentedViewController supportedInterfaceOrientations];
        }
    }

    return orientations;
}

and implement

- (NSUInteger)supportedInterfaceOrientations

in the respective view controllers

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait; //Or anyother orientation of your choice
}

and to perform sudden action against orientation changes, implement the following method

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
0
votes

This is very late for an answer, still I thought I should share this with you just in case,

I had the very same issue.

shouldAutorotateToInterfaceOrientation is deprecated iOS 6 onwards.

You need to parallel this method with the new supportedInterfaceOrientations and shouldAutorotate methods.

And it is very very important, you need to make sure that you set the root controller in your app delegate's applicationDidFinishLaunching method rather than simply adding the view controller's view ( or navigation Controller or tabBar Controller depending on what you are using ) as a subview to the window.