didreceivememorywarning 导致可见视图控制器上的 viewdidunload
当当前可见的视图控制器(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 发送到视图控制器,而该视图控制器显然仍然是查看层次结构。
有什么想法吗?
i am utterly confounded on how to handle memory warnings when the viewcontroller that is currently visible(superview != nil) is being unloaded. The setup is a tabbarcontroller as the rootViewController, a navigation controller with a view controller in it, say view controller A. I push view controller B onto view controller A's navigation stack. I simulate memory warning.
1) view controller A gets a memory warning, and its view is unloaded, all ok.
2) view controller B(currently visible) gets a memory warning. i print out its superview. I even confirmed that the navigation controller's
(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) The next thing I know, the visible view controller's view has been unloaded(A breakpoint in the view controller's viewDidUnload method gets hit)
Because im currently looking at this view controller, its viewDidLoad never gets called again, unless I navigate back to it. This seems to contradict alot of posts out there that say that when superview != nil the view does not get unloaded!, and i have investigated the whole stack!
To clarify, im not asking what to do in viewDidUnload, or what kind of data to release, etc etc. I'm trying to understand why the framework is sending a didReceiveMemoryWarning to a view controller that is clearly still part of a view hiearchy.
Thoughts?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这里要回答你的问题是来自Apple模板的方法存根
,这样你就可以释放内存,仅仅因为你的视图可见并不意味着它正在使用它分配的所有资源。
To answer you question here is the method stub from an Apple template
It's so you can free memory, just because your view is visible does not mean it is using all the resources it has allocated.
视图控制器收到内存警告,因为它们可能正在执行一些潜在的内存密集型操作,因此需要释放内存。假设您有一个用户可能与之交互的数据缓存,但您可以在必要时重新加载。您可能希望将其转储到 didReceiveMemoryWarning 中,因为按需重新加载比由于缺少内存而崩溃要好。但是,您不应该在 didReceiveMemoryWarning 中释放视图或用户当前正在交互的任何内容,否则您将看到您所看到的行为。
此外,正如 Paul.s 的回答中的存根所表明的那样,视图控制器在当前实际上没有被查看时会收到内存警告,因此可以安全地释放其视图。但是,我会将其留给超级的实现(如图所示),因为它已经在那里处理了。
当您收到内存警告时,您是否释放视图(或其中的一部分)?如果是这样,您应该将该代码移至 viewDidUnload。
View Controllers receive memory warnings because they might be doing something potentially memory intensive and therefore need to free up memory. Let's say you had a cache of data that a user might interact with, but which you could re-load if necessary. You would want to dump that in didReceiveMemoryWarning because it would be better to re-load on demand than crash due to lack of mem. However, you should not release a view or anything the user is currently interacting with in didReceiveMemoryWarning or you'll see the behavior you're seeing.
In addition, as the stub from Paul.s' answer indicates, view controllers receive memory warnings when they actually aren't presently being viewed, and its therefore safe to release their view. However, I'd leave that to the super's implementation (as shown), as its already handled there.
Are you releasing the view (or parts of it) when you receive a memory warning? If so, you should move that code to viewDidUnload instead.