Creating a button programmatically - iphone

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 .

Related

what objects can be released immediately after adding to self.view

In a test program, I init 2 UITextFields, 2 UILabels, 1 UITextView and 1 UIButton programmatically in (void)loadview, and I try to release them immediately after [self.view addSubview:controlname] at the last of loadview. All of them work ok except UIButton. So when should I release button? And I wanna know what objects can be released immediately added to self.view?
Thanks a lot.
I'm assuming that you are creating the button with UIButton's +(id)buttonWithType: and if that is the case, you shouldn't release it.
I also would recommend using ARC so that you don't have to worry about this at all.
Well, to release or not to release depends on if you own the object or not, and this depends on how you are creating your objects, From the Memory Management Policy:
You own any object you create:
You create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” (for example, alloc, newObject, or mutableCopy).
Thus, if you created the object with some other method (one that doesn't start with these words) then you should not release it, since you don't own it.

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.

when are objects released

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.

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