didreceivememorywarning导致可见视图控制器上的viewdidunload

时间:2011-07-10 15:56:18

标签: ios memory-management didreceivememorywarning

当完全卸载当前可见的视图控制器(superview!= nil)时,我对如何处理内存警告完全感到困惑。设置是一个tabbarcontroller作为rootViewController,一个带有视图控制器的导航控制器,比如视图控制器A.我将视图控制器B推到视图控制器A的导航堆栈上。我模拟记忆警告。

1)视图控制器A获取内存警告,并且其视图已卸载,一切正常。

2)视图控制器B(当前可见)获取内存警告。我打印出它的超级视图。我甚至确认了导航控制器的

(gdb) po [[self view] superview]
<UIViewControllerWrapperView: 0x12310c80; frame = (0 64; 1024 655); autoresize = W+H;     layer = <CALayer: 0x12310cb0>>>
(gdb) po [self navigationController]
<UINavigationController: 0x714efd0>
(gdb) po [[[self navigationController] view] superview]
<UIViewControllerWrapperView: 0x740b0c0; frame = (0 0; 1024 719); autoresize = W+H; layer = <CALayer: 0x740b140>>

 /*** can you see how desperate i am? : ) ***/
(gdb) po [[[[[self view] window] rootViewController] view] superview]
<UIWindow: 0x7162910; frame = (0 0; 768 1024); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x7163660>> 

3)接下来我知道,可见视图控制器的视图已被卸载(视图控制器的viewDidUnload方法中的断点被命中)

因为即时通讯正在查看此视图​​控制器,所以它的viewDidLoad永远不会被再次调用,除非我导航回它。这似乎与很多帖子相矛盾,这些帖子说当superview!= nil时视图没有被卸载!,我调查了整个堆栈!

澄清一下,我不会问在viewDidUnload中要做什么,或者要发布什么样的数据等等。我试图理解为什么框架将一个didReceiveMemoryWarning发送到一个显然仍然是静止的视图控制器观点层次结构的一部分。

思想?

2 个答案:

答案 0 :(得分:-1)

这里回答你的问题是来自Apple模板的方法存根

- (void)didReceiveMemoryWarning
{
  // Releases the view if it doesn't have a superview.
  [super didReceiveMemoryWarning];

  // Release any cached data, images, etc that aren't in use.
}

这样你可以释放内存,因为你的视图是可见的并不意味着它正在使用它已分配的所有资源。

答案 1 :(得分:-1)

View Controllers接收内存警告,因为它们可能正在做一些可能占用大量内存的事情,因此需要释放内存。假设您有一个用户可能与之交互的数据缓存,但您可以在必要时重新加载。您可能希望将其转储到didReceiveMemoryWarning中,因为由于缺少mem而导致按需重新加载比崩溃更好。但是,您不应该在didReceiveMemoryWarning中发布用户当前正在与之交互的视图或任何内容,否则您将看到您所看到的行为。

此外,正如来自Paul.s'的答案所示,视图控制器在实际上当前没有被查看时会收到内存警告,因此可以安全地释放他们的视图。但是,我将其留给super的实现(如图所示),因为它已在那里处理。

当您收到内存警告时,是否正在释放视图(或部分视图)?如果是这样,您应该将该代码移动到viewDidUnload。