views:

201

answers:

2

Hey.

Instruments' Leaks tells me that this UIImage is leaking:

UIImage *image = [[UIImage alloc] initWithContentsOfFile:[imagesPath stringByAppendingPathComponent:[NSString stringWithFormat:@"/%@.png", [postsArrayID objectAtIndex:indexPath.row]]]];

// If image contains anything, set cellImage to image. If image is empty, try one more time or use noImage.png, set in IB
if (image != nil){
    // If image != nil, set cellImage to that image
    cell.cellImage.image = image;
}
image = nil;
[image release];

(class cell (custom table view cell) also releases cellImage in dealloc method).

I haven't got a clue of why it's leaking, but it certainly is. The images gets loaded multiple times in a cellForRowAtIndexPath:-method. The first three cells' image does not leak (130px high, all the space avaliable).

Leaks gives me no other info than that a UIImage allocated here in the code leaks.

Can you help me figure it out? Thanks :)

+2  A: 

You are setting it to nil before calling release. So you are releasing nil instead of image.

Change from:

image = nil;
[image release];

to:

[image release];
image = nil;
Jason Webb
Oh, I didn't realize that that could cause a leak..! Thanks :)
Emil
What would you use in this situation? What's the difference between these two: `[[UIImage alloc] initWithContentsOfFile:...];` and `[UIImage imageWithContentsOfFile:...];`. Is there any difference at all?
Emil
Not that I really know of. The `imageWithContentsOfFile` is a convenience method. So it is responsible to release the image. If you call alloc then you are responsible. You can read about it in the apple memory management guide here: http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html
Jason Webb
@Jason Haha, like blame it on someone else? Hehe. I need to read that..
Emil
Damn, 50 pages.. No way my printer's gonna take that :(It's times like these I wish I had an iPad, then I could actually get to read Apples documentations.. The HIg is 136 pages long, and gets changed all the time, so I guess theres no point of printing that out either. I need an iPad ..
Emil
Using imageWithContentsOfFile would be the same thing as you sending [image autorelease]. That class method just returns an autoreleased object. Its better to not do that on the iPhone, because you never know when the autorelease pool is going to be drained. With this way, you can be sure that the retain count for the image is modified at the right times.
rickharrison
@rick Won't it release it immedeately if you send `image = nil` ?
Emil
It will only release it if it is a @property. Then if you did self.image = nil, it would release the old contents and set the ivar to nil now.
rickharrison
Okay, thanks. :)
Emil
+3  A: 

The code you have there would be correct if image was a @property. You can release a @property by doing self.property = nil because of the way the setter works. The setter releases the old object and sets the ivar to the value. In order to fix this you would need to put [image release] first. What is happening here is that you set image to nil and then you are essentially doing [nil release]. The old image is just floating around somewhere. So to fix this do the following:

[image release];
image = nil;
rickharrison
Good explantion. Thanks.
Emil
Oh, and what's the point of setting a released object to `nil` anyway?
Emil
Main reason is because if you were to some reason call a method on it, it will not return as EXC_BAD_ACCESS. If you send a message to a released object, your app will crash with EXC_BAD_ACCESS as the reason
rickharrison
That's true (about a @property releasing before setting a new value) ONLY if the setter semantics for the @property is `retain`. If you've used `assign` or `copy` (ie you've said `@property (nonatomic, assign) Type *name`), it won't release on new assign and it will leak. Most of the time you'll be using `retain` there, but it would be helpful to understand what's happening when you do.
Dan Ray
Dan, your right. I forgot to mention that and thank you for clarifying for emil.
rickharrison