简体   繁体   中英

iOS 5 not autorotating view when loadView is called the second time

When I run my app in landscape mode, the second time my view controller's view is loaded and loadView is called, iOS 5 is not rotating the root view controller's view away from portrait, nor is it calling the view controller's willRotate / willAnimateRotation / didRotate methods.

As mentioned, this happens only after the view is unloaded and loadView is called the second time. In my app, I sometimes unload a view controller's view programmatically before I set it as the root view controller. However, this also happens when the view controller's view is unloaded automatically due to a low memory warning.

This only happens on iOS 5, not iOS 4.x. It's easy to reproduce in iOS simulator, and here is a link to a stand-alone test app that reproduces this problem:

http://www.mediafire.com/file/7ob5xw5ym02pasx/ViewControllerTest.zip

To see the issue, just compile the app and start it in landscape mode with iOS 5.0 Simulator, then tap "A" and then "Back", and you'll see how the rotation doesn't occur.

Any ideas? Does this have to do with how I'm setting window.rootViewController ?

I debugged through it and there seems to be a change between 4.3 and 5.0. In 4.3 UIKit calls [UIWindow addRootViewController:] , in 5.0 it calls [UIWindow setRootViewController:] . So maybe something changed that we can't see...

I'd suggest working around this, by not using [newController setupStuff] (thus not setting the view to nil), but rather overriding

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    // do setup stuff here, reset content etc etc.
}

and resetting the (already loaded) view, before it actually appears on screen.

Additional info:

a) you don't need to set the view to nil. The system does that for you. When you access the view property of that view controller the next time, the system calls loadView to recreate the view:

If you access this property and its value is currently nil, the view controller automatically calls the loadView method and returns the resulting view. The default loadView method attempts to load the view from the nib file associated with the view controller (if any).

b) It all boils down to behavior in iOS 5 regarding the window's rootViewController property. In iOS 5 these two are not equivalent:

 self.window.rootViewController = newController;

vs

 [self.window.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
 [self.window addSubview:newController.view];

The former completely ignores orientation, the latter doesn't.

To make things even more complicated, if one does not override loadView , but instead lets the system auto-create an empty UIView and only modifies that view in viewDidLoad , a memory warning won't automatically set the view to nil and release it - docs:

 The default implementation releases the view only if it determines that it is safe to do so. 

Magic. Depending if one overrides the method or not. I can't really test this in any way.

Case 1 - overridden loadView :
Triggering the memory warning calls both didReceiveMemoryWarning and viewDidUnload

Case 2 - no loadView :
Triggering the memory warning in simulator only calls didReceiveMemoryWarning , but not viewDidUnload

I'd say, add the view manually...

cheers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM