When to release dynamically created objects - iphone

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.

Related

Arc: Setting references to nil, for multiple buttons

When displaying an item such as a button in a ViewController, I declare it in the header file:
#property (nonatomic, strong) UIButton *startButton;
Synthesize it in the implementation file:
#synthesize startButton;
Initiate it in the implementation file:
startButton = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
And set the reference to nil in viewDidUnload:
[self setStartButton:nil];
However, what if I have 60 listed items (in a UIScrollView) which are created dynamically in a loop, in viewDidLoad (fed from Core Data)?
(Not using TableView, because the items are quite complicated and interactive.)
Should I declare the items anywhere first? Should I set them to nil anywhere? (Or should I just keep my fingers crossed and pray to the Arc?)
Some guidance would be appreciated. Thanks.
Does your view controller have properties or instance variables that point to each of those 60 items?
Yes: Then set those ivars or properties to nil in your -viewDidUnload.
No: Then there's nothing to worry about.
ARC changes what you do to manage memory, but it doesn't change the basic philosophy, which is that every object should take care of its own references to other objects but not worry about anybody else's.
In this case, the view that contains all those items will have strong references to the items (via it's array of subviews). When the view controller releases its view, that view will then be deallocated and release all its subviews in the process. So all those items will be taken care of. If you did have strong references to any of those items, those references will prevent the referenced objects from being deallocated -- setting the references to nil will avoid that.
If you are creating these views on the fly and adding them as subviews of the scrollView, then you don't need to do anything else.
When the scrollView is released during -viewDidUnload, it will properly clean up all its subviews.
Update
Think of it this way. In a normal view setup on a storyboard, you don't need have a property for every view, only the views your controller interacts with. This is basically the same thing. You have a bunch of views that are embedded into a superview. If the controller doesn't interact with them, then you don't need to worry about them.
no. :)
you definitely set the all pointer to nil what are not necessary anymore when you are using the ARC.
the ARC will release the memory of the current object when there is no more strong pointer who tries to keep alive the object. if you don't set them to nil the ARC thinks you are still using them and they will be in the memory and they will cause serious memory leak.
UPDATE #1
if you have any reference for the buttons this is the easiest way to do it, you don't need to do set to nil anything, because their superview class retain them and you should just remove from their superview.
for (UIView *_subView in self.view.subviews) {
if ([_subView isKindOfClass:[UIButton class]]) {
[_subView removeFromSuperview];
}
}
if you're storing their pointer any other place (in an NSArray for ex.) you must have to remove the pointers from them as well.

UIView Delete Itself?

I have a UIView subclass called ToolbarView that sort of acts like a floating window and has a UIToolbar that has an "X" button that can make the window disappear. My question is, is it possible for the object to delete itself from within its own class?
For instance, within ToolbarView.m, I have a method closeButtonPushed which fires when the X button is pushed. Is it as simple as to remove the view from its superview, and then call dealloc? Is it even necessary to call dealloc as once it is removed from the superview there won't be any other pointers to it. Or is this bad memory practice?
Yeah, don't call dealloc ever. If the superview is the only object that has a reference to your view, removing the view will cause its retain count to go to 0, and the runtime will then deallocate the object for you.
What you have to do is in closeButtonPushed method is, call
[self removeFromSuperView];
it will remove the ToolbarView object and IOS will call the dealloc method and release objects. No need to call dealloc manually.

How to release subviews

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

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