iPhone Development - Release an autoreleased object - iphone

What happens if I release an autoreleased object? Its an autoreleased UIButton I want to release and the only way to create a UIButton is to use the convinience method buttonWithType:. Will it be released from memory like a normal object? Or should I just let the autoreleasepool take care of it? I wouldn't have made it autoreleased in the first place if I could.
Thanks!!

You should just let the autorelease pool take care of it. Once you add your button to a parent view, that view will retain it, and the autoreleased handle will get taken care of by the autorelease pool.
The easiest way to think of it is in terms of ownership—you don't "own" the reference you got via a convenience method, so you don't need to bother releasing it unless you retain it as well.

You must only release an object which you own. +buttonWithType: does not return an owned object, so you must not release it.
Review the Cocoa Object Ownership Rules.
Why are you trying to avoid an autoreleased object here? Presumably you are creating the button because you are using the button and inserting it into a view hierarchy, so there is no real reason to accelerate the draining of the autorelease pool which contains the button.

Related

Should I release an UIImageView added to my view if I will detect touch on it later on?

I've learnt that if you create an object, you own it and need to release it when you're done with it. In this case I create an UIImageView and add it to my view like this:
myImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"image.png"]];
[myImageView setFrame:CGRectMake(10,10,100,100)];
[self.view addSubview:myImageView];
[myImageView release];
If I later on want to detect touch on myImageView like this in my touchEnded-method:
if([touch view] == myImageView){
NSLog(#"TOUCHED!");
}
This works, but is this correct, since I now used myImageView after releasing it?
And how do I release myImageView from the self.view that I added it to earlier?
The cardinal rule of Cocoa memory management is that you should retain those things you care about, and release those things you do not care about. There are a very small number of exceptions to prevent retain loops (delegates and datasources are never retained), but this is the rule you should follow.
In this case, if you are storing the image in an ivar, I would continue to retain it, regardless of the fact that its superview will always retain it, and so you don't "have" to. But if the view is removed from its superview, you will wind up with a dangling pointer, and then you will crash, so I code defensively against that by retaining. If you used an accessor here (which you should), then this would be automatic and much safer.
Apple has grown more consistent about this in iOS, switching their recommendation about IBOutlets. On Mac, you do not retain your IBOutlets, but in iOS, Apple explicitly instructs you to do so. This is similar to the situation you are discussing, and I agree with Apple's move towards a safer approach.
As long as your myUIImageView object has a retain count > 0, it will still exist and you can continue using it. When you first add it as a subview, it gets a retain message so it's retain count is likely 2. Then you send it release, so its retain count is reduced to 1. This means it still exists in memory. Now, if you sent it release again, or sent it removeFromSuperView then its retain count would be zero, and you'd lose it.
The behavior is erratic, sometimes you may see it works, sometimes you get a crash.
If you want to use that variable to point to your image view, retain the ivar (by using a retain property). This way you ensure that the image view is available for your controller class to use.
Assuming myUIImageView is an ivar of your custom UIView subclass, your code will work as long as your image view stays in his superview. The image view instance may be deallocated and you may end with an invalid pointer referencing a deallocated object. At best you crash.
According to memory management guidelines, you should consider your image view <-> custom uiview subclass relation as wether:
strong reference. You own the image view (as you created it), and are responsible for retaining / releasing it
weak reference. You don't own the object, thus keeping a reference to it may be dangerous.
in your case, it's probably a strong reference. your myUIImageView ivar should be a nonatomic retained property of your object.
If you need to access your UIImage at some point in the future, you need to retain it.
How you do this is at your discretion, but you should not rely on the UIView to retrain your objects for you. The situation you've created works for now, but it's fragile.

How should I manage the memory allocated for the UIView returned from viewForHeaderInSection?

I'm about to implement the UITableViewDelegate::viewForHeaderInSection method, where I plan to allocate and init a new UIView object and return it. I'm new to iOS development, but I'm trying to adhere to the general rule of thumb that if I create it, I'm responsible for deleting it, but I can figure out how the UIView object is handled after I pass it on to the UITableView. Should I autorelease the UIView object? Should I store it in an instance var and release it in my dealloc?
Thanks for your help!
I would autorelease the UIView.
I would only store it in an instance variable if you need an reference to it later.

whats the difference between releasing an object inside dealloc or releasing in the same method where we init it?

HI,
I am working on optimizing my iphone project for proper memory management.
my question is:
what's the difference between releasing an object inside dealloc or releasing in the same method where we init it?
Thanks!
Generally, you want to release an object as close to the point in the code where you initialize it as possible. If you have local variables in a method that you are init-ing, you release them before the method returns.
This, however, is not possible with instance variables, since they stick around with the objects; thus, you release them in a dealloc method.

Does this have to be released?

I've done a lot of research on when it's correct to release things, but it's all confusing to me. I think sometimes the Leaks program is off. Anyway...
background is a UIImageView
background.image = [UIImage imageNamed:#"greenbackground.png"];
Do I have to release background? I never alloced it and it's not set as a property, so I'm thinking no.
Actually, you do need to release it.
UIKit uses Key Value Coding to assign IBOutlets to a controller. By default this is causing your controller to increase the retain count by one. From the KeyValueCoding docs:
If you have not defined a setter, then UIKit will directly set the value of the instance variable and then, for anything other than an NSNumber or NSValue date type, UIKit will retain the value after autoreleasing the instance variable’s old value.
Unless you explicitly set a #property with assign, you need to release the object.
No you don't. That factory method returns an autoreleased UIImage. A good rule of thumb that helps me in objective c is whenever you see alloc, copy or new in a method name... you are incharge of releasing the returned object... everything else should be an autoreleased object. Also, I can't think of any class level methods (+) in the api that don't return autoreleased objects.
EDIT
I read your question too quickly... Mark is correct on this. If you are ever in doubt about these kinds of things you can always do a simple test and log the retain count.
Mark's right that you are responsible for releasing your UIImageView if it is instantiated from a nib, if background is an IBOutlet, and if background does not have a corresponding "assign" property.
Even if you're managing that correctly, you may still see some extra memory in use in ObjectAlloc after you release your UIImageView. That's because -[UIImage imageNamed:] caches the image you load in anticipation of you calling -[UIImage imageNamed:] again later. The image is not necessarily uncached even when the returned UIImage gets deallocated.

NSObject release... Still shows up in ObjectAlloc

I have been tracking down why NSObject references, while being explicitly release, still show up in ObjectAlloc. In fact, have reduced down NSObject to a basic shell, with a [[myObject alloc]init] immediately followed by a [myObject release], and it does not look like it is being released in ObjectAlloc. This is a big problem with a NavigationController app that pushes/pops multiple view controllers, as the recently popped viewcontrollers aren't being released, because of these 'unreleased' NSObject references. Hmmmmmm.
I could put my code up here, and have a bunch of 'have you's that never get anywhere. Autorelease pools, blah blah.
So, let's look at the Sample 'SeismicXML' sample app from Apple... fire it up in ObjectAlloc/Leaks. Very basic in getEarthquakeData:
XMLReader *streamingParser = [[XMLReader alloc] init];
[streamingParser parseXMLFileAtURL:[NSURL URLWithString:feedURLString] parseError:&parseError];
[streamingParser release];
I see a TON of junk laying around in ObjectAlloc from XMLReader, despite releasing it. I bet if we put a 'refresh' button on this app to call 'getEarthquakeData' again, we would crash the app within 5 refreshes.
Any thoughts?
I think you are confused about the ObjectAlloc instrument which will show all object allocations for the lifetime of your application. It's main use is to track memory usage over time.
The instrument I think you want is the one that is called Leaks which shows you what memory is being leaked by not having any reference to it. That is pointers to objects not being sent release-dealloc before they are reassigned.
There might be an autorelease pool holding onto the object. If you create many autoreleased objects without cleaning them out of the pool, you'll get leaks until you return to the outer loop with the autorelease pool.
Here's how autorelease pools work: in the main loop, there's an autorelease pool. Everything autoreleased goes there. At the end of every loop iteration, all the objects in the pool get released. If you allocate objects in another loop somewhere, they won't actually get released until you return to the main loop. Unless, of course, you create your own autorelease pool just for the loop.
Another problem could be that your object is never released. If you get an exception between +alloc and -release you'll get a leak. A way to fix this is to use instead:
[[[XMLReader alloc] init] autorelease]
Finally, you could be working with garbage collection here. I don't know enough about the GC system to tell you what behavior you should expect.