简体   繁体   English

iOS 5不会在第二次调用loadView时自动旋转视图

[英]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. 当我以横向模式运行应用程序时,第二次加载视图控制器的视图并调用loadView ,iOS 5不会将根视图控制器的视图旋转离开肖像,也不会调用视图控制器的willRotate / willAnimateRotation / didRotate方法。

As mentioned, this happens only after the view is unloaded and loadView is called the second time. 如前所述,只有在视图被卸载并且第二次调用loadView之后,才会发生这种情况。 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. 这仅在iOS 5上发生,而不在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: 在iOS模拟器中很容易重现,这是一个重现此问题的独立测试应用程序的链接:

http://www.mediafire.com/file/7ob5xw5ym02pasx/ViewControllerTest.zip 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. 要查看此问题,只需编译该应用程序,然后使用iOS 5.0 Simulator以横向模式启动它,然后依次单击“ A”和“ Back”,您将看到旋转不会发生。

Any ideas? 有任何想法吗? Does this have to do with how I'm setting window.rootViewController ? 这与我如何设置window.rootViewController吗?

I debugged through it and there seems to be a change between 4.3 and 5.0. 我调试了它,似乎在4.3和5.0之间进行了更改。 In 4.3 UIKit calls [UIWindow addRootViewController:] , in 5.0 it calls [UIWindow setRootViewController:] . 在4.3中,UIKit调用[UIWindow addRootViewController:] ,在5.0中,它调用[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 我建议通过使用[newController setupStuff] (因此将视图设置为nil)来解决此问题,而应覆盖

- (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. a)您不需要将视图设置为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: 下次访问该视图控制器的view属性时,系统将调用loadView来重新创建视图:

If you access this property and its value is currently nil, the view controller automatically calls the loadView method and returns the resulting view. 如果访问此属性,并且其值当前为nil,则视图控制器将自动调用loadView方法并返回结果视图。 The default loadView method attempts to load the view from the nib file associated with the view controller (if any). 默认的loadView方法尝试从与视图控制器关联的nib文件中加载视图(如果有)。

b) It all boils down to behavior in iOS 5 regarding the window's rootViewController property. b)归结为iOS 5中有关窗口的rootViewController属性的行为。 In iOS 5 these two are not equivalent: 在iOS 5中,这两个相等:

 self.window.rootViewController = newController;

vs 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: 使事情变得更加复杂的是,如果不覆盖 loadView ,而是让系统自动创建一个空的UIView并仅在viewDidLoad修改该视图,则内存警告不会自动将视图设置为nil并释放它-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 : 情况1-覆盖loadView
Triggering the memory warning calls both didReceiveMemoryWarning and viewDidUnload 触发内存警告调用didReceiveMemoryWarningviewDidUnload

Case 2 - no loadView : 情况2-无loadView
Triggering the memory warning in simulator only calls didReceiveMemoryWarning , but not viewDidUnload 在模拟器中触发内存警告调用didReceiveMemoryWarning ,而不是viewDidUnload

I'd say, add the view manually... 我会说,手动添加视图...

cheers. 干杯。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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