黑屏 - 在viewWillAppear中,superview是零

loc*_*ope 8 view objective-c superview ios

我有一个从选项卡式应用程序模板创建的应用程序.(ARC,iOS 4)

  • 有几个选项卡,2. tabs选项卡viewcontroller.view(ViewCont2)上有一个按钮.
  • 此按钮通过presentModalViewController方法加载另一个viewcontroller的(ModalViewCont)视图.
  • ModalViewCont上有一个关闭按钮,它调用dismissModalViewControllerAnimated.
  • 在ViewCont2的viewDidDisappear中,我将self.view = nil和其他出口设置为nil以卸载视图,以便下次在屏幕上显示时它将被新加载.我这样做是因为它继承自基类(BaseViewCont),它初始化视图控制器的一些常规属性,并在viewDidLoad方法中添加一些按钮,标签等.因此,从此基类继承的ViewControllers可以在viewDidLoad方法中以不同方式配置这些属性.

问题

现在,当ModalViewCont在屏幕上,按Home键将应用程序放在后台并在获得应用程序后,关闭ModalViewCont不会带回ViewCont2的视图,而是带有底部标签栏的黑屏.没有放置应用程序背景/前景就会发生同样的事情; 如果在点击2.制表符之前点击其他选项卡.(编辑:只有在viewWillDisappear中将self.view设置为nil而不是viewDidDisappear时才会发生这种情况.)

我确定ViewCont2加载一个新视图(检查它的引用)但是视图的superview是nil所以新视图不会显示而是显示黑屏.

事情没有用

  • 使用[self.view removeFromSuperview]; 在设置self.view = nil之前,
  • 在viewWillAppear中向父级添加视图; [self.parentViewController.view addSubview:self.view]; 这个没有顺利工作,视图略微放在屏幕上.这是因为层次结构中还有其他几个超级视图.

我考虑的解决方案

  • 1-如果viewDidLoad中的superview为nil,则它在viewWillAppear (假设)中可用.因此,ViewCont2的viewWillAppear方法可用于通过以下方式正确加载superview;

_

if (self.view.superview == nil)
{
    self.tabBarController.selectedViewController = nil;
    self.tabBarController.selectedViewController = self;
}
Run Code Online (Sandbox Code Playgroud)
  • 可以使用2- viewWillAppear基类方法进行初始化,因此无需卸载视图.因此,可以优化性能,每次视图消失时都不会卸载.此外,最好只通过检查一个标志执行一次初始化,而不是每次出现时都执行它.

问题

  • 1-为什么超级视图没有恢复?我该怎么办呢?(这是我想要理解和解决的主要问题,而不是尝试替代方案......)
  • 2-我是通过分配nil来查看卸载它而做错了吗?如果是这样,我应该如何在这种情况下正确卸载视图(选项卡式应用程序)?
  • 3- 解决方案有什么问题吗?它看起来像一个kludge?那是关于上海华和viewWillAppear中的假设是否正确?

编辑:似乎早于它应该调用viewDidLoad时(即在viewWillDisappear而不是viewDidDisappear中查看视图时),不设置superview.

Fel*_*lix 6

这看起来很奇怪,但你的建议(1)确实是解决这个问题的正确方法:

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

    if (!self.view.superview) { // check if view has been added to view hierarchy
        self.tabBarController.selectedViewController = nil;
        self.tabBarController.selectedViewController = self;
    }
}
Run Code Online (Sandbox Code Playgroud)

你的第二个建议是有利于性能(因为视图加载是一项昂贵的操作) - 但它不能解决问题.在以下情况下,您也可以使用黑屏而不将视图设置为nil(在iOS模拟器中测试):

  1. 打开模态视图
  2. 模拟内存警告 - >这将卸载tabbarcontroller中的视图
  3. 按主页按钮再次打开应用程序
  4. 关闭模态视图 - >黑屏

通常,您可以假设在viewDidLoad中设置了view属性,并且在viewWillAppear + viewDidAppear中,视图已添加到视图层次结构中; 所以superview应该在那时(这里superview是类UIViewControllerWrapperView的tabbarcontroller的私有视图).但是在我们的情况下,虽然重新加载视图(在应用程序恢复时),但它不会添加到视图层次结构中,从而导致黑屏.这似乎是UITabBarController中的一个错误.

解决方法强制再次执行外观选择器.因此,将再次调用viewWillAppear,这次使用superview.viewDidAppear也会被调用两次!

将self.view设置为nil是可以的,但在大多数情况下不应该是必需的.让系统决定何时卸载视图(iOS可以在内存变低时卸载视图).应该以某种方式设计视图控制器代码,以便可以随时重新配置UI而无需重新加载视图.