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?

  • Resident memory vs live bytes
  • iPad low memory warning, although no other apps are running, and my app allocates only 8 MB
  • How to rotate sub-views around their own centres?
  • iOS 6 UIInterfacePortrait ONLY viewcontroller being presented & stuck in landscape… when coming back from a landscape viewcontroller in nav stack
  • iOS 6.0 restrict auto rotation within a navigation controller?
  • Disable autorotate on a single subview in iOS8
  • 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.