when are objects released - iphone

I believe I have to release an object if I created it with the keywords init, alloc, copy, or move I believe. I may create objects with code that don't use this keywords so I guess I don't have to release them right? so take for instance this code:
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(aMethod:)
forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Hello" forState:UIControlStateNormal];
button.frame = CGRectMake(40.0, 200.0, 170.0, 40.0);
[self.view addSubview:button];
since I did not use any of those keywords in my code I should not release it right? so when is that object being released? I am little confused with the memory managment stuff.

The only object you created here is the UIButton, and you used the buttonWithType class method. That is returning you autoreleased object, so you don't have to release it.
Keep in mind though that if you were to need this button at a later time you would need to retain it and eventually release it. Because you add this button to a view, the view retains a copy in this case so again you don't need to worry about it.

If you're running XCode 4 I recommend running the 'analyze' mode to run quick basic check for memory leaks... that looks fine (your code).

You are absolutely correct in that you don't have to explicitly release anything that you don't take ownership of via alloc, copy, new, or retain.
In this case, you've created the button via a convenience method (buttonWithType:). This returns an autoreleased UIButton object. This is released automatically when the autorelease pool is flushed at the end of the run loop.
There's nothing for you to worry about here. Let the runtime take care of it.

There is an NSAutoreleasePool that manages the memory for you. You were correct about alloc and copy (alloc and init are usually together) but not move. Another one that returns a retained object is methods prefixed with new ex. +(id)new;. An auto release pool is required for each thread to manage memory for each event loop.
An example of how a button implementation may look
-(id)buttonWithType:(UIButtonType)type
{
UIButton *button = [[[UIButton alloc] initSecretlyWithType:type] autorelease];
//Customize button if needed
return button;
}
See Using Autorelease Pools for more details.

Related

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

Creating a button programmatically

I have seen 2 ways to create button.
UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(10, 220, 150, 30)];
and
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
The first case is the normal way to create a button object. I have allocated and initialised a button instance and I have to release that. I am really confused about the second way. I have some questions regarding this.
Is a button instance created in this case?
What is the retain count of this button?
Should I release this button?
Hope this helps:
Yes button instance is created.
Retain count will be how do you add/retain.
You don't need to release button if you have not created it by alloc.
Is a button instance created in this case?
Yes, an instance is created.
What is the retain count of this button?
The retain count is probably one, otherwise the lifecycle would get rid of it.
Should I release this button?
No, you shouldn't the object is autoreleased.
From: http://cocoadevcentral.com/d/learn_objectivec/
On local memory management:
There's only one rule: if you create an object with alloc or copy, send it a release or autorelease message at the end of the function. If you create an object any other way, do nothing.
Yes a local instance is created
1, but will be 0 when the function ends
No, the object will be marked for release when the function ends provided you don't call retain on it.
1.)Yes the button instance will be created whether you allocate it or by using factory method.In both the cases button instance will be created
2.)The retain count will be 1 for the current run loop/cycle,Then on the next loop, the object will be auto released. Thus the retainCount will be 0. (Note: NSLogging a retainCount of 0 will crash the app)
3.)No you don't have to release the button created with factory methods,They are released automatically .

UIButton causing crashes

This is a very simple issue but I have no idea why it's happening. In my header file, I've declared a UIButton *leftButton. In the viewDidLoad method I do this leftButton=[UIButton buttonWithType:UIButtonTypeRoundedRect];
Then in some other method I have:
leftButton.frame=newFrame;
leftButton.tag=i;
[leftButton addTarget:self action:#selector(leftButtonSelected:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:leftButton];
However I keep getting a crash when the above method is called. Sometimes I get a message, other times it just crashes with no message. I can't really replicate any crash messages, now all I'm getting is just a general crash, but it kept crashing from weird issues such as [UIGestureRecognizer setFrame] is causing problems or [WebView setFrame] or something..for some reason it keeps thinking that leftButton is something else than a UIButton, but this is not the case. There is nothing else named leftButton in my entire project. Any ideas?
Your first method is returning an autoreleased object, most likely it has been released by the time your second method is called. Either retain the button in the first method or use a retained property to hold on to it rather than an ivar.
Also, remember to release this in your dealloc method at the end.

OpenFlow crashes app whem trying to reset/ recreate

I am trying desperately to change the images on an OpenFlow instance with no luck.
I am kind of giving up so I am trying now to remove the instance and create a new one. But I can't avoid crashing the app.
The code to create it is:
AFOpenFlowView *of = [[AFOpenFlowView alloc] initWithFrame:CGRectMake(0, 100, 320, 380)];
[of setCenter:CGPointMake(160, 240)];
[of setBackgroundColor:[UIColor blackColor]];
[of setDataSource:self];
[of setViewDelegate:self];
[self setPeopleFlow:of];
[self.view addSubview:peopleFlow];
[of release];
Then, on a click of a button I do:
[peopleFlow removeFromSuperview];
[peopleFlow release];
Later on I call the same function with the first block of code to create it again and it's when the application crashes with no log error.
Any ideas on how to clean the OpenFlow object to repopulate it without having to remove/recreate? Or how create/recreate reliably?
When you create the peopleFlow instance, it has a retain count of 1.
Then when you add it as a subview, the super view retains it, so it's retain count is 2.
Then you release it after adding it to the superview, so it's retain count is 1 again.
Then You remove it from the superview, and the superview releases it, so it's retain count is 0 and the object gets deallocated.
Then you try and release it again, and it crashes because you're sending release to a deallocated object.
Long story short, in this case, you don't need to release it after removing it from the superview.
Also, it is good practise to assign nil to a pointer if you release it and don't care about what is pointing at any more. This is because after you release and deallocate an object, the pointer variable is still pointing to the memory that the object used to occupy. Assigning nil to the pointer prevents any bad stuff happening if you try to send a message to whatever the dangling pointer is pointing to.

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