Why Doesn't iOS Autorotate a View loaded from a Nib after it was released by didReceiveMemoryWarning?

My iPad app makes heavy use of autorotation. This is great. However, I’ve noticed that if a hidden view is released by the default implementation of didReceiveMemoryWarning (as described here), when the view is re-loaded from the nib and I happen to be in landscape, it loads it in portrait. This wreaks havoc with the interface until I rotate the iPad manually and force it to go to the proper orientation.

I had assumed that iOS would load the view in the current orientation; that’s what it does when the app launches. But it no, not after being unloaded by didReceiveMemoryWarning. Why not? And how can I get it to do that?

  • Required initializers for a subclass of UIViewController
  • Navigating back to main ViewController dismissViewControllerAnimated dilemma
  • Creating a first launch viewcontroller
  • Swift popToRoot not working
  • Keep getting “Unbalanced calls to begin/end appearance transitions for <ViewController>” error
  • Prevent access to UIViewControllers with tab bar controller (storyboard)
  • 2 Solutions Collect From Internet About “Why Doesn't iOS Autorotate a View loaded from a Nib after it was released by didReceiveMemoryWarning?”

    The answer, determined thanks to pointers from dbarker, is that the view controller’s rotation methods, including -willRotateToInterfaceOrientation:duration: and -willAnimateRotationToInterfaceOrientation:duration:, will not be called when a view is reloaded after a the default implementation of didReceiveMemoryWarning has unloaded the view. I’ve no idea why it would be different on app launch, but I do have a workaround

    What I did was to set a boolean ivar, named unloadedByMemoryWarning, to YES in didReceiveMemoryWarning, like so:

    - (void) didReceiveMemoryWarning {
        unloadedByMemoryWarning = YES;
        [super didReceiveMemoryWarning];
    }
    

    Then, in viewDidLoad, if that flag is true, I set it to NO and then call the rotation methods myself:

    if (unloadedByMemoryWarning) {
        unloadedByMemoryWarning = NO;
        [self willRotateToInterfaceOrientation:self.interfaceOrientation duration:0];
        [self willAnimateRotationToInterfaceOrientation:self.interfaceOrientation duration:0];
        [self didRotateFromInterfaceOrientation:self.interfaceOrientation];
    }
    

    Kinda sucks that I have to do this, but it does work, and now I’m less concerned about getting killed by iOS for using too much memory.

    1. I think iOS 5 might fix this.

    2. For iOS 4.3, I’ve had good luck with another fix. After the load from nib:

      [parent.view addSubview:nibView];  
      nibView.frame = parent.view.frame;  
      [nibView setNeedsLayout];  
      

      If that worked, you could jettison the unloadedByMemoryWarning logic, since it’s safe to do every load. Got the tip & code (basically) from here.