Deallocating and removing UiButtons - iphone

I am trying to make a program that dynamically creates a button using the command:
[UIButton buttonWithType:UIButtonTypeRoundedRect]
But when I use these commands the delete the button I create:
[currentButton removeFromSuperview];
[currentButton dealloc];
[currentButton release];
I receive an error. How would I go about removing and deallocating the memory from a uibutton?

I got this problem long time ago, please notice that
[UIButton buttonWithType:UIButtonTypeRoundedRect]
has autorelease inside, so in your initialisation you need to do retain, like this:
_mybutton = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
and later point, you can do:
[_mybutton release];
Hope helps
:)

In the Objective-C/Cocoa framework, you encounter two different ways to receive objects: ones which you have explicitly allocated memory for (via a constructor) and ones that you have received memory reference to (via a class method).
FooBar *fone = [[FooBar alloc] initWithText:#"Hello, World!"];
In this example, memory is explicitly being allocated for the object by your call, using the alloc method, and then it is being initialized with data using the initWithText method that would have a method header like this:
- (id)initWithText:(NSString *)text;
On the other hand, you also will encounter objects that are created by classes automatically for you. An example of this would be below:
FooBar *ftwo = [FooBar fooBarWithWelcomeText];
In this example, a FooBar object is being returned even though we are not calling alloc to allocate memory for it. There are many different reasons to implement the method like this, but its mainly done to abstract certain details from the code that is using the object. The above example would have a corresponding method header like this:
+ (FooBar *)fooBarWithWelcomeText;
Depending on which approach is used, it changes how you interact with the memory of the object. So for the first example, after allocating the memory for the object you receive it back with a retain count of 1. If you are done using the object, you need to explictly release it with
[fone release];
In the second example, you are receiving an autoreleased object, which will be deallocated once the autoreleasepool is drained. If you want to keep it, you must explicitly retain with:
[ftwo retain];
If you do not wish to retain it, you can just leave it as is and it will be deallocated automatically. You can tell a method uses autorelease by two characteristics: 1) you will not utilize alloc when you receive the object; and 2) there will be a "+" next to the method heading. This means that the method is declared as a class method (similar to Java static methods).
So to finally answer your specific situation, you only need to make sure that the retain count is lowered to 1 (The only object having a reference to it was the autorelease pool). In your example, it would be done like this:
UIButton *currentButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[someView addSubView:currentButton];
// some code later
[currentButton removeFromSuperview];
You do not need the release statements because you never explicitly retained it. When you added the UIButton to another view, it retained the object so it incremented the reference count to 2. By removing it from the view, it is lowered back down to 1 so that when the autorelease pool is flushed, your UIButton will be deallocated. Btw, never call the dealloc method directly. When the retain count of an object is decremented to 0, the dealloc method will automatically be called.

You can't not dealloced the UIButton which you get through buttonWithType from system,if you don't alloced any instance then you are not entitled to call release on that.
In your case, you can use removeFromSuperview but not either dealloc or release .
You can't call dealloc directly on object, this is invoked by the system when you say release on object.
EDITED:
you could create you button using initWithFrame function of UIView. But you will get only the button type UIButtonTypeCustom which is by default, and also can't not change the button type because it's readonly property. So you would get the rounded button by using your some images.

You're not supposed to call dealloc directly. Try removing the dealloc line and see how that works.

Related

What's the equivalent of '[[something retain] autorelease]' in ARC?

What's the equivalent of [[something retain] autorelease] in ARC?
I have a problem where a class DBRequest calls my delegate to signify completion. My delegate then sets the DBRequest instance to nil, which dealloc's it. But then when the stack pops out of my delegate and jumps back to the DBRequest, it of course then crashes.
If I wasn't in ARC, in my delegate I'd simply do [[theDbRequest retain] autorelease] before releasing my reference to it, so that it'd survive long enough until the next run loop autoreleased it.
What should I do in ARC?
How about adding something like
__strong DBRequest * myself = self;
[delegate reportDone];
I think that'll increment the self object until the end of the function preventing it from dying early.
My delegate then sets the DBRequest instance to nil, which dealloc's it. But then when the stack pops out of my delegate and jumps back to the DBRequest, it of course then crashes.
Surely this was always a bad strategy, and your [[theDbRequest retain] autorelease] was always just covering up the problem, yes?
Simply do nothing. So your instance variable sticks around; so what? You know that ARC will release it for you when you are dealloced.
The important thing is not to release theDbRequest, but to set theDbRequest's reference to you (the delegate) to nil, so it doesn't try to call you back when you no longer exist. Your own dealloc would be a good place to do that.
Hope I'm understanding the issue correctly. If not, post some code!
As #matt says if you simply do nothing ARC should clean up when your object is deallocated - assigning the DBRequest you create to an instance variable handles that (provided of course your object outlasts the object you are creating).
If you need to deallocate the DBRequest before your object dies then you need an ARC-compatible "trick" equivalent to [[theDbRequest retain] autorelease]. Now unless you are constructing your own auto release pools your previous approach would trigger at the end of the current event. Following that logic try:
Add a method to your class which simply sets theDbRequest to nil, let's call this cleanUpTheDbRequest.
Change your delegate callback to invoke [self performSelectorOnMainThread:#selector(cleanUpTheDbRequest) withObject:nil waitUntilDone:NO] instead of directly assigning nil to theDbRequest
This should delay the assigning of nil till after the end of the current event, just as your autorelease "trick" did. It also works if your DBRequest lives across multiple events - the previous method kicks in at the end of the event the autorelease is called in, this method at the end of the event the delegate method is called in.

iPhone Memory Management

There are a few concepts about iPhone memory management that have got me confused, so I was hoping that someone could clarify these.
(a) Say that I am calling a function which returns an image, and I want to store that returned image in a variable so that I can assign it to various other variables without having to re-call the image generation function each time. At the moment I am doing the following:
UIImage *storedImage = [someFunction returnImage];
and because the storedImage is not alloc'ed I am not releasing the variable.
However, should I be explicitly alloc'ing and releasing the UIImage instead?
UIImage *storedImage = [[UIImage alloc] init];
storedImage = [someFunction returnImage];
...do stuff...
[storedImage release];
What is the implication of doing the direct assignment without alloc rather than alloc'ing the variable and then assigning?
(b) In the init method for various classes I am setting up the instance variables. At the moment I am doing the following:
self.arrayVariable = [[NSMutableArray alloc] init];
However, I have seen others do the assignment this way:
theArrayVariable = [[NSMutableArray alloc] init];
self.arrayVariable = theArrayVariable;
[theArrayVariable release];
or
theArrayVariable = [[NSMutableArray alloc] init];
arrayVariable = theArrayVariable;
[theArrayVariable release];
...which is the same as above, but without the self.
What is the difference between the three methods and which is better to use?
Regarding returning objects from methods, you should always return an autoreleased object from any method which does not begin with the name alloc, new, or contains copy. This is defined in Apple's object ownership policy, which states that you own any object that you create ("create" is defined as an object which you sent retain to, or used any of the aforementioned messages to retrieve an object), and that you are responsible for relinquishing ownership of that object by sending it the release or autorelease message.
The first method using self uses the property setter to set the instance variable to the argument (in this case whatever is on the RHS of the assignment).
This will do whatever you specified in your #property declaration (for example if you specified retain, the setter will retain the new value and release the old value).
The second method sets up a pointer to an NSMutableArray and passes it off to your property setter via self, which will most likely retain it, thereby bringing the reference count up to 2, since the object was previously alloc-ed, so you need to release it after this line to bring it back down to 1.
The third method will not work, because you are releasing an object with a reference count of 1 at the point of invoking release. How so you ask? Well, the first line sets up a pointer to an alloc-ed object, then directly assigns it to your instance variable, which will just point the ivar to the same object that theArrayVariable is pointing to. Then, that same object that theArrayVariable is pointing to gets sent the release method, which will effectively bring down the reference count of your ivar as well as the receiver, to 0. At this point both your instance variable and theArrayVariable will get deallocated.
a) The general rule for objective-c is that if you alloc it you must release it. In the first example, the method is returning a pointer to an object that already exists, and therefore you are not responsible for releasing it. In the second example, the first like is pointless since you aren't using allocated memory for stored image. This may cause a memory leak.
b) The first two are just stylistic differences, with no difference in outcome. In those, you will be left with arrayVariable pointing to the object returned by [[NSMutableArray alloc] init]; (assuming you have retain in the #property declaration) and you should release it in the -dealloc method. As stated above, the third will not work because you are merely passing off the pointer.
Here is a useful article for understanding obj-c memory management: http://memo.tv/memory_management_with_objective_c_cocoa_iphone
a) The code you gave does not do what you want. When you say
UIImage *storedImage = [someFunction returnImage];
someFunction returns an image object to you, but it does not guarantee that the image object will live forever. If you do not want the image to be freed without your permission in a future time, you should own it by calling retain like this:
UIImage *storedImage = [[someFunction returnImage] retain];
So now, this image object is owned by both someFunction and you. When you finish your work with this object you release it by calling release. When both someFunction and you call release for this object, it will be released (Of course if it is not owned by another owner).
In the other code segment, you create an image object and own it by calling
UIImage *storedImage = [[UIImage alloc] init];
But then you lose its reference by assigning a new object to the storedImage pointer by calling someFunction. In this situation the image created by you is not freed but continues to live somewhere in the memory.

Objective-C (iPhone) ivars and memory management

I am subclassing NSURLConnection, and used MGTwitterEngine as a base to help me get started. That may be irrelevant. However, I noticed in their code they don't use #property or #synthesize for their ivars. They have wrapped the ivars in accessor methods which look like this:
- (NSString *)identifier {
return [[_identifier retain] autorelease];
}
My question is two part. First, what effect does retain followed by autorelease have? It seems to me it would cancel itself, or worse yet leak.
Second, if I were to change the header file to have:
#property (nonatomic, retain, readonly) NSString* _identifier;
And used #synthesize indentifier = _identifier, wouldn't this do the same thing as the accessor method without having to write it?
Maybe it is just two different ways to do the same thing. But I wanted to ensure I have the correct understanding. Thanks.
Using #synthesize will actually only create a setter and a getter method. The code that is auto generated for you is guaranteed to use proper memory management, so that you do not need to worry.
MGTwitterEngines use of return [[ivar retain] autorelease] is actually the correct way to do it. Lets have two examples.
Assume a getter is defined as this:
-(Foo)foo {
return foo;
}
And then we execute this code:
bar = [[bar alloc] init]; // bar has aretain count of 1.
foo = bar.foo; // foo har a retain count of 1 (owned by bar).
[bar release]; // Bar and all it's ivars are released imidiatetly!
[foo doSomething]; // This will crash since the previous line released foo.
If we instead change the getter to this:
-(Foo)foo {
return [[foo retain] autorelease];
}
bar = [[bar alloc] init]; // bar has a retain count of 1
foo = bar.foo; // foo has a retain count of 2 (one owned by bar, 1 owned by autorelease pool).
[bar release]; // Bar and all it's ivars are released imidiatetly!
[foo doSomething]; // Will not crash since foo is still alive and owned by autorelease pool.
Hope this explains why you should always return properly autoreleased objects from all your getters. It is important that any return value can survive the deallocation of it's parent, since no class ca guarantee what a client will do with it's values once it is exposed to the wild.
Retain followed by autorelease does exactly what you might think it does. It sends the object a retain message and then sends it an autorelease message. Remember that autoreleasing an object adds that object to the autorelease pool but does not release it yet. The autorelease pool will send the object a release message at the end of the current iteration of the run loop. So, a retain followed by autorelease essentially says, "Make sure this object stays around until the end of the the current iteration of the run loop." If you need the returned value to hang around longer, you can retain it. If not, do nothing and the autorelease pool will handle it.
In this case, the string being sent retain and autorelease messages is a property. It's already retained by the parent object. So you might wonder why do this retain and autorelease thing at all? Well, there's no guarantee that the object won't release _identifier before the current iteration of the run loop ends. Consider this example:
- (NSString *)identifier { return _identifier; }
- (void)aMethod {
NSString *localId = [self identifier]; // localId refers to _identifier which is only retained by self
[self methodThatChangesIdentifierAndReleasesItsOldValue]; // self releases _identifier
NSLog(#"%#", localId); // crash, because localId (old value of _identifier) has been released
}
In this case, the returned identifier isn't retained and autoreleased. The NSLog line crashes because localId refers to a released string. However, had we used retain and autorelease in the getter, there would be no crash because localId would not be released until the end of the current iteration of the run loop.
As far as I know, your replacement with an identifier property would be just as good. It might not be identical code, but the effect should be the same.
Apple explains this well in Implementing Accessor Methods. The method quoted by you (named "Technique 1" by Apple) helps avoid bugs if the caller assigns a new value to the identifier property and then expects the retrieved value to still be available. It won't be needed most of the time but just returning the ivar value can lead to bugs that are hard to track down.
Generally one retains then autoreleases if you are returning something that you didn't own the first place. It will only leak if you own _identifier and there is a mismatch of retain/alloc/etc versus release/autorelease sent to that object.
Secondly, yeah you generally don't have to write the headers if you aren't doing something special beyond what the general boilerplate looks like. Apple has good documentation on properties, I suggest if you're still fuzzy, you look at those.

Where I should call [object release]?

I've subclassed some UITextField and added some custom properties.
In a UITableViewController, in the ViewDiDLoad I init them, and in the cellForRowAtIndexPath I add them to the cell with [cell.contentView addSubview:customTextField];
Each cell has a different customTextField as all of them are very different.
Where I should call the [customTextField release] ?
After I add them to the cell view ?
If for example I call [self.tableView reloadData] my customTextField are going to be added again to the cell, so maybe I should change my approach in doing this ?
thanks for the orientation ...
regards,
r.
You release an object when you no longer have any interest in it. This happens for many reasons; it might be because you've finished with the object, or have passed the control over the object lifetime to another object. It might be because you're about to replace the object with a fresh instance, it might be because you (the owner object) are about to die.
The last one seems to be relevant in your case. You create these object in viewDidLoad and repeatedly need them (i.e. to add them to cells) until your object is no longer functioning. In this case, just as you create them in viewDidLoad, you can release them in viewDidUnload.
Edit: I should really mention autorelease, but this isn't relevant in this instance. Memory management is best handled with a notion of 'owner' - the person who creates something (or retains it) should be responsible for deleting it (or releaseing in ObjC parlance). autorelease handle some cases where you need to give an object to an alternate owner, having previously owned it yourself (typically via a method return). If you are the creator, you can't just release it before returning it to the new owner, as it will be deleted before the new owner has a chance to stake an interest in it. However, you can't just not release it; it will leak. As such, the system provides a big list of objects that it will release on your behalf at some point in the future. You pass your release responsibility to this list, then return the object to the new owner. This list (the autorelease pool) ensures your release will occur at some point, but gives the new owner a chance to claim the object as theirs before it's released.
In your case, you have a clear interest in owning the objects for the lifetime of your view controller - you need to, at any time, be able to add them to view cells in response to a table data reload. You're only done with them when your view controller dies, so the viewDidUnload (or possibly dealloc) is the only sensible place to release them.
I always release my controls directly after I added them to a view using addSubView. When I work with tables, I also initialize them in the cellForRowAtIndexPath method.
Therefor the object stays alive the shortest time.
Adam Wright explains the theory of this very well, but let me give you some practice. You're thinking about this problem far too hard, and that almost always leads to bugs. There is a simple solution that solves this problem almost every time: Retain all ivars using accessors; don't retain non-ivars.
.h
#interface ... {
UITextField *_customTextField;
}
.m
#property (nonatomic, readwrite, retain) UITextField *customTextField;
...
#synthesize customTextField=_customTextField;
-(void)viewDiDLoad {
self.customTextField = [[[UITextField alloc] init....] autorelease];
}
...
- (void)dealloc {
// I do not recommend accessors in dealloc; but everywhere else I do
[_customTextField release]; _customTextField = nil;
}
Never access your ivars directly, except in dealloc (even that is controversial and some people recommend self.customTextField = nil; in dealloc; there are arguments either way). But never assign your ivars directly. If you will follow this rule, you will find that most of your memory problems go away.
The safest way to handle object ownership is to autorelease the view directly after initialization:
FooTextField* textField = [[[FooTextField alloc] init] autorelease];
[myCell.contentView addSubview:textField];
Adding the text field to a superview (the UITableViewCell's contentView) retains it. This way you don't have to care about releasing the view afterwards.
There seems to be a resentment against autorelease in the iPhone developer community. In my opinion, this resentment is unfounded. Autoreleasing an object adds very little overhead to the program if the objects lives longer than the current pass through the run loop.
Every object in Obj-C has a reference counter (retainCount), and when this counter goes to 0 the object is deallocated. When you allocate and initialize an object, the reference count is set to 1 - but you can retain it as many times you want to.
UITextField *textField = [[UITextField alloc] init]; // Reference counter = 1
[textField retain]; // Reference counter = 2
[textField retain]; // Reference counter = 3
The opposite of retain is release, which subtracts from the reference counter;
...
[textField release]; // Reference counter = 2
[textField release]; // Reference counter = 1
You can always get the reference counter of your objects;
printf("Retain count: %i", [textField retainCount]);
The method addSubview of UIView does retain your passed in sub view - and when it's done with it it releases it. If you need your UITextField later, in another scope (when the UIView is done with it and has released it) - you should not release it after you've added it to the super view. Most of the time you actually don't need to hold on to a reference, so you should release it after you've added it to the super view. If you dont - you can release it in the dealloc method of your scope.
Take a look at UITableView -dequeueReusableCellWithIdentifier: and -initWithStyle:reuseIdentifier:.
In -tableView:cellForRowAtIndexPath:, use -dequeueReusableCellWithIdentifier: and check if the result is nil. If it is, instantiate a new cell with -initWithStyle:reuseIdentifier:.
Send -autorelease to your customTextField upon creation and adding to the respective cell.
You should not add subview in cellForRowAtIndexPath! This will slow down the view as you add a subview each time the cell is displayed. Try using custom UITableViewCell class for that purpose.
Here is a perfect solution of UITableView customization
http://cocoawithlove.com/2009/04/easy-custom-uitableview-drawing.html
works jut perfectly

Autorelease and "assign" properties in Objective-C? (On iPhone)

I have an instance of a UITableView, and a separate class that adheres to the delegate and datasource protocols. I'm doing this like so:
SubjectTableViewHandler *handler = [[[SubjectTableViewHandler alloc] init] retain];
tv.delegate = handler;
tv.dataSource = handler;
[handler autorelease];
I don't want to maintain the handler as an ivar, and if I take off the retain call at the end, when the autorelease happens, it is sent release, then added to the pool, which causes an EXC_BAD_ACCESS. So currently, the retain count is:
(1) At init: 1
(2) At retain: 2
(3) delegate/datasource properties are 'assign', still 2
(4) At autorelease: 1, now in autorelease pool.
But then since the properties are 'assign', they will never be released, the retain count will never hit 0, and the handler will never be deallocated anyway. Is there any more efficient way to accomplish this than maintaining the handler as an ivar and releasing it in the dealloc method?
When you initialize the object using init, you are claiming ownership of it and there is no reason to call retain. You also don't want to call autorelease since that will cause the object to be released at the of the run loop.
Since you need to keep the handler (so that your tableView can call the delegate/dataSource methods) and a reference to the handler after the method returns (so you can release it when you are done showing the tableView), the cleanest approach would be to make it an ivar.
The only solution that I can see is, as you mentioned, to make it an ivar and store, allocate, and deallocate it in parallel with the table.
It all depends on your use of table view.
Common practice is you create a view controller which is a delegate to table and table may be a controller's member.
As another alternative you can inherit from UITableView and make it delegate of itself.
Sometimes it's better to use a singleton delegate.
Also, in table delegate methods first argument is tableview, so one delegate object can service multiple tables.