didreceivememorywarning causes viewdidunload on visible view controller
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(开发者_StackOverflowA 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?
To answer you question here is the method stub from an Apple template
- (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.
}
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.
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.
精彩评论