0

当当前可见的视图控制器(superview!= nil)被卸载时,我对如何处理内存警告感到非常困惑。设置是一个作为 rootViewController 的 tabbarcontroller,一个导航控制器,其中有一个视图控制器,比如视图控制器 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 发送到显然仍然是视图层次结构的一部分的视图控制器。

想法?

4

2 回答 2

-1

视图控制器收到内存警告是因为它们可能正在做一些潜在的内存密集型操作,因此需要释放内存。假设您有一个用户可能与之交互的数据缓存,但您可以在必要时重新加载这些数据。您可能希望将其转储到 didReceiveMemoryWarning 中,因为按需重新加载比由于缺少内存而崩溃要好。但是,您不应在 didReceiveMemoryWarning 中释放视图或用户当前正在与之交互的任何内容,否则您将看到您所看到的行为。

此外,正如 Paul.s 回答中的存根所表明的那样,视图控制器在当前实际上没有被查看时会收到内存警告,因此释放它们的视图是安全的。但是,我将把它留给 super 的实现(如图所示),因为它已经在那里处理了。

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

于 2011-07-10T17:49:40.420 回答
-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.
}

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

于 2011-07-10T16:13:31.973 回答