How to release subviews - iphone

In my iPhone/iPad app,
I am adding one subview to my main view.
This subview has one imageview and button.
When to release them ?
My code is here,
customAlertView=[[UIView alloc] initWithFrame:CGRectMake(0, 0, 600, 600)];
UIImageView *imgv=[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"celebration.png"]];
UIButton *btnOK=[UIButton buttonWithType:UIButtonTypeCustom];
[btnOK setTitle:#"OK" forState:UIControlStateNormal];
[btnOK addTarget:self action:#selector(alertOKClicked) forControlEvents:UIControlEventTouchUpInside];
[customAlertView addSubview:btnOK];
[customAlertView addSubview:imgv];
[self.view addSubview:customAlertView];
[imgv release];
[btnOK release];
In one another method I am writing the code.
[customAlertView removeFromSuperview];
My confusion is imageview and button is there If
I release the customalertview here will it releases its subviews automatically.
If yes then no problem.
If NO how to release it
as I have done here released the objects immediately after adding subviews.
It will cause my OK button Unworthy. And will not affect the button click.
So, On removing from superview should I write.
[[customalertview subviews] release];

Your code is correct.
You release them after you've added them to the alert view, as the alert view takes care of retaining them. When you call removeFromSuperview, it'll get released automatically.

I think the points you are missing, based on your comments on the existing answers, are the following:
A view retains its subviews - so if you create a new view object, and add it as a subview to something else, you can then safely release it, unless you'd like to keep a reference around for it yourself.
When a view is removed from its superview, it is released. So if there are no more objects retaining it, it will be deallocated.
When a view is deallocated, it will automatically release all of its subviews, and so on down the tree.
Enable ARC as soon as you are able to.

You are doing it the right way. The customalertview will releases its subviews automatically.
Your object will be released when the release count go to 0, that means in the theory, and if you are coding well, that this object does not have any reference to it anymore.
While you maintain your custom alertView in your view, you have an object retaining your things, so the release count will not be 0 until you remove the customAlertView, because you have added they to the customAlertView, and when you remove the alert, the alert will be released, and all the things that it is retaining will be released too.
Hope it help you to understand how things work.
If you want to know more about memory management you can take a look at apple documentation here
EDIT:
I forgot to mention that you will need to release your custom alert too after you remove it.
If you do not understand the memory management you also can take a look at: http://cocoadevcentral.com/d/learn_objectivec/ section 7

Related

When to release dynamically created objects

In my iPad App,
I have one custom class inherited from UIButton.
I am adding the buttons on my main view dynamically using for loop.
This button has also has label.
My problem is when to release the Custom Class's Objects.
for(NSMutableDictionary *dict in Categories)
{
Category *category=[[Category alloc] initWithName:[dict valueForKey:#"category_name"] identity:[[dict valueForKey:#"category_id"] intValue] imageName:nil];
category.lblimagesCount=[[UILabel alloc] initWithFrame:CGRectMake(category.frame.size.width-31, category.frame.origin.y-42, 26, 26)];
[category addSubview:category.lblimagesCount];
[self.viewHeader addSubview:category];
[category release];
category=nil;
}
How to avoid memory leaks.
Especially for
1. labels
2. Category class.
Where to write release ?
i. Category class(UIButton) has its dealloc method but it is never called.
ii. As I am releasing it immediately after adding it to the subview , Will it affect my button click.
iii. When should I release the labels.
Very confused about the memory management.
I'll answer your questions:
i. Category class(UIButton) has its dealloc method but it is never called.
Because its not totally released, see question ii.
ii. As I am releasing it immediately after adding it to the subview , Will it affect my button click.
No, because your subview is now the owner of the button, when you add it to the subview, both you and the subview are owners, when you release, the button now is owned by the subView.
iii. When should I release the labels.
As soon as you add then to the subview, for the same reason as the question ii.
I'll be happy to clarify if you dont understand it.

is removeFromSuperview releases the object?

I am using removeFromSuperview for removing a view from its superview. I am also using release after removeFromSuperview on that object, sometimes its work fine but sometimes give bad access.
is removeFromSuperview also call release to the object ?
Yes, removeFromSuperview also releases view.
You need to release your view after you have added it to its superview.
CGRect frame; // let's assume you already have defined frame and superview
UIView *superview;
UIView *subview = [[UIView alloc] initWithFrame:frame];
[superview addSubview:subview];
[subview release];
Or just use autorelease, when you create a view.
UIView *subview = [[[UIView alloc] initWithFrame:frame] autorelease];
[superview addSubview:subview];
In both cases, you don't need to call release after you call removeFromSuperview.
Yes, addSubview calls retain, and removeFromSuperview calls release. So your call to release does not belong there (it probably belongs after you assign the subview, assuming you do not want to hold the object).
The correct answer is "probably". This is an implementation detail that you shouldn't even really be thinking about. If your code needs to work with the subview, then you should be retaining it before you start working on it, and you should be releasing it when you're finished working with it (which may or may not coincide with removing it from it's superview).
I imagine testing would show that removeFromSuperview does release the view, but you cannot depend on this behaviour and should never assume it will happen. Even if it does always happen now it might not in future.
You shouldn't even need to think about memory management at such a low level as this. If you retain the object with retain or copy or alloc or new then you are responsible for counter-acting that with a release at some point in the future.
If you did not do any of these things, then you should not be releasing it. The methods for adding a subview to a view do not contain retain or copy in their name and therefore you are not supposed to release it yourself when you remove it from it's superview.
The view system is very complicated, especially on an iPhone with such a limited amount of RAM and not inadequate storage to use virtual memory. Stick to the rules and you should be fine. Or enable ARC.
Actually removeFromSuperview decreases the retainCount property of the view Object and so as the release.
So,if you do the way Aleksejs said.
UIView *subview = [[UIView alloc] initWithFrame:frame];
[superview addSubview:subview];
[subview release];
subview -> alloc= retainCount = +1 ,
subview -> addSubView = retainCount = +1
subview -> release = retainCount = -1.
subview -> removeFromSuperView = retainCount = -1
(subview removed from memory)

(iphone) uiimage, view, subviews memory management

I need to release uiimage/view/subviews when I want, and have a few questions regarding proper practice of releasing them.
[imageView removeFromSuperview] would release the imageView and imageView.image?
view = nil; would release its subviews/and associated uiimages recursively? if not, should I implement a recursive function to release a view's subviews?
Thank you
Edit.
I looked at UIView's library reference
addSubview --
This method retains view and sets its
next responder to the receiver, which
is its new superview.
removeFromSuperview --
If the receiver’s superview is not
nil, the superview releases the
receiver. If you plan to reuse a view,
be sure to retain it before calling
this method and release it again later
as appropriate.
still not sure [imageView release] releases uiImage associated with it,
and would I still need recursive releasing of subviews. ie a view's getting dealloced would automatically guarantee it's subviews release?
[imageView removeFromSuperview] would
release the imageView and
imageView.image?
removeSuperView calls release on the view, but you should pay attention to the views retain count. Just because you called removeFromSuperview doesn't mean it's doing what you want.
view = nil; would release its
subviews/and associated uiimages
recursively? if not, should I
implement a recursive function to
release a view's subviews?
No, you probably want to do (depending on how you've managed your subviews during their creation. If the superview was their only reference, they likely have a retain count of 1 and therefore calling release after calling removeFromSuperview will result in an error):
for (UIView* subview in view){
[subview removeFromSuperView];
[subview release]
}
[view release];
EDIT: To answer your final question, no, calling release on a view does not automatically call release on all of its subviews. You have to do it yourself, whether with release or with removeFromSuperview.
When you do [imageView removeFromSuperview], it won't release anything. You need to so [imageView release] afterward. Even so, you still need to put your memory releasing for that view in imageView's dealloc.

iPhone: Do I have to (and how) release the subviews of a custom table view cell?

I have got custom TableViewCell-s where I assign several UIImageView-s and UILabel-s to the cell's contentview, like this:
[cell.contentView addSubview:iconFileView];
[iconFileView release];
[cell.contentView addSubview:areaLabel];
[areaLabel release];
[cell.contentView addSubview:placeLabel];
[placeLabel release];
As I understand the cells themselves are retained by the TableView and will be released together with it. However, I do not understand do I have to remove the cell's contentview's subviews from the contentview in order for them to be released?
If the answer is yes: how do I actually do that? Is it sufficient to find all the visible cells and remove their subviews from each cell?
Neither could find an exact answer to this question in Memory Management Guide for Cocoa.
Thanks!
The contentView will take care of releasing its subviews when the cell releases the contentView. Basically, when cell's retain count goes to zero, it will send a release message to contentView. If contentView's retain count is zero, then it will send release messages to all its subviews, including iconFileView, etc. As long as you haven't sent any additional retain messages to contentView or iconFileView, etc., you should be fine.
If you want to feel really good, run your program under Leaks in Instruments. Make sure you do whatever needs to be done to cause the UITableViewCells to be released.

UIButton - should we release or not?

I want to add a button on a view dynamically. Here is the code.
UIButton *x=[UIButton buttonWithType:UIButtonTypeRoundedRect];
Here, I have not used "alloc" function.
The questions for this statements are as follow.
If we are using imageview for the same situation, we have to create an temp imageview add to your current view and release it. What to do for button?
How are buttons allocated and de-allocated?
If buttons are allocated? How it's memory is been managed?
Now when I use [x release]; - is it right or wrong?
No alloc/init or new so it will be autoreleased when it is no longer needed. When you add it to the UIView the count is increase and retained by the view, then also released when the view is released.
You do not need to call release in this case. Since you are using a convenience constructor, the object that is returned is an autoreleased object.
If you use an alloc / init form, you are responsible for releasing the object.
UIButton *x=[UIButton buttonWithType:UIButtonTypeRoundedRect];
using this method u cant relese the button
instead of use
UIButton *x = [[UIButton alloc]init];
and then release