What is the use of viewDidUnload and didReceiveMemoryWarning methods?
When they actually get called?
what are the difference between dealloc, viewDidUnload and didrecievedmemorywarning?
viewDidUnload: It is called when viewcontroller recieves the low memory warning.
dealloc: It is called when the object/viewController is released.
didRecieveMemorywarning: Also called when the controller recieves the low memory warning.
So Whats the difference between viewDidUnload and didrecieveemoryWarning?
viewDidUnload is the place where you need to clean up the UI related things i.e., outlets.
didRecieveMemoryWarning is a place where you need to clean up the other objects which are holding memory and not used frequently.
viewDidUnload is supposed to undo what viewDidLoad does, just like dealloc is supposed to free up whatever resources init created. So:
-(id)init {
if (self == [super init]) {
foo = [[Foo alloc] init];
}
return self;
}
-(void)dealloc {
[foo release];
[super dealloc];
}
-(void)viewDidLoad {
[super viewDidLoad];
bar = [[Bar alloc] init];
}
-(void)viewDidUnload {
[bar release];
[super viewDidUnload];
}
didReceiveMemoryWarning is there so you can free up any unnecessary memory. Perhaps you cache images. That's nice to have, for a snappy UI, but when memory's tight you can release that memory and your application's performance can degrade gracefully.
It's a good idea to start with Apple's documentation, as there is a lot there about this subject.
viewDidUnload is called when a UIViewController subclasses unloaded it's view. The view is then released, and all IBOutlets are disconnected. The method is usually fired when a viewController is popped, or when it recieves a memory warning.
didRecieveMemorywarning is called when the OS sends a memory warning. This happens when the device is low on memory. You should try a release as much data as possible here, to free up memory. Caches, data that is not needed at the moment, etc.
If you don't free up memory, your app will be killed at a certain point to free up memory for the OS.
Dealloc is called when the instance is deallocated.
Related
I am new to iPhone development.
I am using some buttons and labels in my app. I am releasing all these buttons and labels in dealloc function.
I am also releasing them in viewDidUnload.
- (void)viewDidUnload
{
[super viewDidUnload];
self.ans1 = nil;
self.ans2 = nil;
self.ans3 = nil;
self.ans4 = nil;
self.button = nil;
self.button2 = nil;
self.button3 = nil;
self.button4 = nil;
}
I just want to know that it is good for memory management or it makes no difference to memory management.
And why we use that??
Thanks in advance..!!
it is not the view controller that is unloaded when viewDidUnload is called but only its view. The view controller stays alive until it is deallocated.
In viewDidUnload, you have to release those objects that are part of the view and everything that can and will be recreated in viewDidLoad (because viewDidLoad will be called again when the view controller need to recreate its view). This includes all your outlets. You also have to set these variables to nil to avoid overreleasing them.
Because in dealloc, you should release all objects your view controller retains, including those you included in viewDidUnload.
viewDidUnload is used to release anything that you might have made when the view is created - this included things in viewDidLoad but also includes and IBOutlet properties that are created from inside a xib file. these should all be released and set to nil in viewDidUnload.
Anything else should just be released in dealloc.
The idea is that if viewDidUnload is called to free some memory, the view can be recreated again completely from your viewDidLoad method.
Also see this question;
memory management on the iPhone with viewDidUnload
It is good for memory management. If you release objects associated with a View controller when the controller unloads, you effectively reduce the memory footprint of your application. Retaining objects even when you are not using them makes your application more prone to memory warnings & eventual termination.
Hence, it is good practice to allocate in ViewDidLoad & release in ViewDidUnload.
HTH,
Akshay
I would be interested in anyone who can provide a little more information regarding Apple's recommendation below (found in the Core Data tutorial) re nil'ing objects in "viewDidUnload". For example:
why this is important? different between releasing an nil'ing?
is this best practice / I haven't been doing this nor seeing this I don't think in some iPhone example code I've looked at?
Code:
// The implementation of viewDidUnload should relinquish ownership
// of anything created in viewDidLoad that can be recreated.
- (void)viewDidUnload {
self.eventsArray = nil;
self.locationManager = nil;
self.addButton = nil;
}
- (void)dealloc {
[managedObjectContext release];
[eventsArray release];
[locationManager release];
[addButton release];
[super dealloc];
}
Setting the properties to nil will release them as well (assuming the setter method releases the old value as it should do).
Additionally, setting the properties to nil means that any messages that might end up getting sent to them afterwards will be swallowed by nil and ignored. In the situation where they were simply released, the object might get deallocated and overwritten in memory, but they could still have messages sent to them (now being sent to whatever overwrote them in memory), likely causing a crash, an exception, or other unexpected behaviour.
The viewDidUnload method will get called when we have a low memory situation. In low memory situations, the xibs will be released from memory to free memory for the app. But that won't be effective enough if we are still retaining the nib objects in our app. So when we set our nib objects to nil in viewDidUnload we are helping to free more memory.
I am finishing up an iPad application, and for me, that means filling in all of the dealloc methods in my classes.
I have many views in my nib and most of them contain subviews (i.e. UIViews, UILabels, etc.). Should I release the child views before releasing the parent? If the parent view is released, will its child views be released, as well?
Sample:
-(void)dealloc
{
[super dealloc];
[childView release]; // Do I need this if I use the next line?
[parentView release]; // Will this perform the line above?
}
Both childView and parentView are properties of my view controller. Both have been retained.
Anything that you have retained (whether explicitly or through a retained property) needs to be released for the memory management to be balanced.
Also, you should invoke [super dealloc] at the end of your dealloc implementation, not the beginning (for instance, because you might depend on superclass resources still being available at the time).
By the way, saving your dealloc-writing until you're finishing up work on the app is a backwards way to go. I know it seems like house-cleaning work, but the fact is until you're managing memory properly, you're going to have a very skewed view of how your app really performs.
Ideally you should write your dealloc calls as you write your #synthesize statements. In other words, you add a property to your class, you set it up as a retained property, you write its #synthesize and -release code. That way you know your memory management is basically clean (I mean, at the class property level anyway) and you can code with confidence.
Since you specified that you have subviews from a NIB, it sounds like you also may need to pay close attention to the viewDidUnload method.
Any views which are automatically allocated from the nib you can implicitly release by setting the outlet to nil. For example:
- (void)viewDidUnload {
[super viewDidUnload];
self.subviewOutletOne = nil;
self.subviewOutletTwo = nil;
}
Then for any objects which you explicitly retain, you release them in the dealloc method like you are planning to do:
- (void)dealloc {
[myDataArray release];
[coolAnimatedImage release];
[myCustomSubview release];
[super dealloc];
}
Also be sure to check out the LEAKS instrument. This is a random tutorial for using the built in leak analysis tool. There may be others / better ones. It can a pain to get up and running the first time but is completely worth it.
I saw this code in the project template and a few other sample projects.
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
Can someone explain to me what self.myOutlet = nil does? Does it release the memory? I thought you put [myOutlet release] in - (void)dealloc to release the memory. what is = nil? and when do you need to do this?
If myOutlet is specified as a #property (retain) then whenever you assign it to point to a new object, the old one will be released and the new one retained. When you assign it to nil, that therefore releases the object that it previously pointed to.
Typically viewDidUnload method is called when low memory warning occurred and controller's view gets unloaded (controller itself stays in memory). As David pointed in his answer usually outlets are being retained by controller so they stay in memory even after the main view is gone - that reduces the benefits of unloading the view.
You still need to release you outlets in dealloc method even if you release them in viewDidUnload
For more details see this SO question
I have developed a simple location aware iPhone application which is functionally working very well to our expectations except in the low memory condition of the phone .
In low memory condition of the phone my app just crashes and If I increases the phone memory by freeing up some space it again start working well without any crash .
when I did some googling on the problem I found that in the low memory conditions the OS will send didReceiveMemoryWarning to all the controllers in the current hierarchy so that each one of them should implement didReceiveMemoryWarning method and also set iboutlet to nil for the view that is currently not visible .
I have also read somewhere that if the view for that controller is not visible the method setView with nil parameter will be called and if there are some outlet variables attached to view there will be problem in removing them.
So with all these fundas what is the best to handle low level memory condition raised by the Iphone by implementing the didReceiveMemoryWarning and viewDidUnload methods.
Please give a proper example or link if possible for the solution of the above problem .
thanks.
One example i am posting...which i have copied from somwhere... it might give you some idea...
- (void)didReceiveMemoryWarning {
// Release anything that's not essential, such as cached data (meaning
// instance variables, and what else...?)
// Obviously can't access local variables such as defined in method
// loadView, so can't release them here We can set some instance variables
// as nil, rather than call the release method on them, if we have defined
// setters that retain nil and release their old values (such as through use
// of #synthesize). This can be a better approach than using the release
// method, because this prevents a variable from pointing to random remnant
// data. Note in contrast, that setting a variable directly (using "=" and
// not using the setter), would result in a memory leak.
self.myStringB = nil;
self.myStringD = nil;
[myStringA release];// No setter defined - must release it this way
[myStringC release];// No setter defined - must release it this way
/* 3. MUST CONFIRM: NOT necessary to release outlets here - See override of
setView instead.
self.labelA = nil;
self.imageViewA = nil;
self.subViewA = nil;
*/
// Releases the view if it doesn't have a superview
[super didReceiveMemoryWarning];
}
Memory warnings are a signal to you that you should dispose of any resources which aren't absolutely critical. Most of your controllers will be hanging onto data caches, intermediary data, or other bits and pieces, often to save recalculation. When they receive memory warnings, they should begin flushing anything they don't immediately need in order to operate.
How you determine what is "critical" depends entirely on your application's design. An OpenGL game, for example, may determine that textures currently on-screen are valuable and flush textures which aren't visible, or level data which is outside the bounds of the current play area. An application with extensive session logs (like an IRC client) may flush them out of memory and onto disk.
As you observed, the warning is sent to each controller in your hierarchy, so each piece needs to determine individually what data constitutes "critical for operation" and what constitutes "expendable". If you've optimized them all and are still getting out of memory warnings, it's unfortunately time to revisit your core application design, because you're exceeding the limits of the hardware.
On iOS 5 and earlier.
When controller receive a memory warning, didReceiveMemoryWarning will be called. At that time, if controller's view is not in the view hierarchy, the view will be set to nil and viewDidUnload will automaticly invoked. So the things we must do in viewDidUnload is releasing sub view created in viewDidLoad or created from Nib. Like this:
- (void)viewDidUnload
{
self.subView = nil;
self.subViewFromNib = nil;
}
- (void)didReceiveMemoryWarning
{
self.someDataCanBeRecreatedEasily = nil;
[super didReceiveMemoryWarning];
}
On iOS6.
The controller doesn't automaticly release the view when receive a memory warning. So the viewDidUnload never be called.
But we still need to release our view (including sub view) when a memry warning happens.
Like this.
- (void)didReceiveMemoryWarning
{
if ([self isViewLoaded] && [self.view window] == nil) {
self.view = nil;
self.subView = nil;
self.subViewFromNib = nil;
}
self.someDataCanBeRecreatedEasily = nil;
[super didReceiveMemoryWarning];
}
Note that we don't call [self view] before we know the view is loaded. cause the this method will automaticly load view if the view is not loaded.
Note that we can release the view just when the view is not added to a window.
It's up to you to decide what to do in didReceiveMemoryWarning. The OS is telling you that memory is low, and you need to free up as much as you can as soon as you can. The idea is that you should free any cached data, unload views that aren't visible, etc. The details are application specific.
You could also release memory in didReceiveMemoryWarning, that you allocated for static variables in your classes. Because once the memory for static variables is allocated it'll not be freed during the application runs.
To my surprise, only a few apps in the official iPhone samples implement didReciveMemoryWarning. You can use the iPhoneCoreDataRecipes example as an reference.
Some samples (e.g. TableViewSuite) even do something else ;-)