在我的应用中,我以编程方式根据用户操作更改根视图控制器,例如登录/注销功能。
在iOS 8中 - 我注意到一个奇怪的问题。即使在窗口上设置rootViewController之后,旧的层次结构仍然存在。我只是通过捕获视图层次结构来验证它。
- (void) logout{
[self.window setRootViewController:[self loadLoginView]];
}
-(UIViewController *) loadLoginView{
WelcomeScreenVC *wsVC;
wsVC = [[WelcomeScreenVC alloc] initWithNibName:@"WelcomeScreenVC" bundle:nil];
UINavigationController *onboardingVC = [[UINavigationController alloc]initWithRootViewController:wsVC];
return onboardingVC;
}
即使在执行此行代码后,旧的登录视图层次结构仍然存在。如果有人能够提出幕后发生的事情,我将不胜感激。
编辑:我只是看了一下UIWindow的setRootViewController文档,这里是Apple对它的评价:
根视图控制器提供窗口的内容视图。将视图控制器分配给此属性(以编程方式或使用Interface Builder)将视图控制器的视图安装为窗口的内容视图。如果窗口具有现有视图层次结构,则在安装新视图之前将删除旧视图。
我注意到了同样的事情。
基本上,我有一个相当复杂的故事板,充当登录/欢迎界面。此界面位于导航控制器中,该控制器以模态方式呈现另一个导航控制器。
在某一点之后,用户采取将他转换到主界面的动作。使用iOS 8视图调试器我注意到在设置窗口的rootViewController属性后,旧的视图层次结构仍然存在。
我的解决方案,现在是在重新配置window.rootViewController属性之前使用以下代码:
for (UIView* subView in self.window.rootViewController.view.subviews) {
[subView removeFromSuperview];
}
[self.window.rootViewController.view removeFromSuperview];
它不漂亮,但它的工作原理。
我注意到的另一个奇怪的事情是,使用此方法未正确清理欢迎界面的模态呈现的viewController。我必须手动解雇它并清理它。
var loginNavigationController: OnBoardViewController?{
willSet{
if newValue == nil {
loginNavigationController?.view.removeFromSuperview()
}
}
}
loginNavigationController = nil然后设置window.rootviewcontroller = {Different VC}
最好的解决方法是:
self.window.subviews.forEach { $0.removeFromSuperview() }
或者,旧式:
for view in self.window.subviews {
view.removeFromSuperview()
}