Question

In direct reference to this question:

How to stop rotation of ABPersonViewController & ABNewPersonViewController in Landscape mode in iphone

How can I prevent this screen from rotating in iOS 6 when I am not the one pushing the view controller? Scenario being I create a new contact, and the user then presses either the 'Create new contact' or 'Add to existing contact' buttons. The screen produced is the ABNewPersonViewController but because I do not have direct access to the rotation methods, I am unable to prevent it from rotating.

Screenshot:

enter image description here

The above image is taken from a subclass of the ABUnknownPersonViewController, in this subclass the only functionality I have implemented is to override the rotation methods as follows:

- (BOOL)shouldAutorotate
{
    return NO;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
    if(toInterfaceOrientation == UIInterfaceOrientationPortrait)
        return YES;

    return NO;
}

However, the issue is, I cannot then subclass the ABNewPersonViewController screen that is pushed when one of the buttons in the above image is pressed to override the rotation on iOS 6. Any ideas on how I can legitimately get access to these buttons OR override the rotation on the screen that is pushed to prevent it from doing so?

UPDATE 1:

I attempted to create a category on the ABNewPersonViewController and ABUnknownPersonViewController that overrode the rotation methods (not ideal, I know) and then globally imported, but this did not work. Other than this, I am completely stuck for ideas on how to override this behaviour. Any suggestions?

UPDATE 2:

Is it possible to gain a reference to the buttons in that UITableView and override the methods they call? Or is this in violation of Apple terms by accessing private APIs? Trying to investigate this approach so far and not really getting anywhere.

Was it helpful?

Solution

On iOS 6, rotation handling has changed. There are two options to prevent the rotation:

  1. You can set your whole app to only support portrait orientation in your Info.plist.
  2. You can override a method in your application delegate:

    - (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
    {
        return UIInterfaceOrientationMaskPortrait;
    }
    

    As that method is called on your delegate whenever the orientation changes or a new view controller is pushed, you can even use it to temporarily disable landscape display:

    // In AppDelegate.h:
    @property (nonatomic) BOOL portraitOnly;
    
    // In AppDelegate.m:
    - (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
    {
        return _portraitOnly ? UIInterfaceOrientationMaskPortrait : UIInterfaceOrientationMaskAllButUpsideDown;
    }
    
    // to switch to portrait only:
    ((AppDelegate *)[UIApplication sharedApplication].delegate).portraitOnly = YES;
    
    // to switch back to allowing landscape orientations as well:
    ((AppDelegate *)[UIApplication sharedApplication].delegate).portraitOnly = NO;
    

Both methods are perfectly acceptable for App Store submission, as these only use published and documented behavior.

OTHER TIPS

Going off of Tammo Freese answer. I assume the view that needs to be allow landscape is lower in the view stack than your custom ABUnknownPersonViewController. If so in your ABUnknownPersonViewController subclass over add this

- (void) viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    ((AppDelegate *)[UIApplication sharedApplication].delegate).portraitOnly = YES;
}
- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:(BOOL)animated];    
    ((AppDelegate *)[UIApplication sharedApplication].delegate).portraitOnly = NO;
}

In iOS 6 what orientations view controllers are allowed to rotate to is controlled by the top-most full screen view controller, and autorotation methods are no longer called down the view controller hierarchy.

Instead of creating a subclass of the ABPersonViewController, create a subclass of UINavigationController with this code:

- (BOOL)shouldAutorotate
{
    return NO;
}


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
    return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}


- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

Use this new subclass when creating the UINavigationController for the ABPersonViewController you are presenting. If the UINavigationController is not being presented modally (and is instead nested in a UITabBarController or another view controller), you will need to also put these methods in that view controller as well.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top