views:

394

answers:

5

Any ideas why the line below would be leaking memory?

cell.imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:person.imageURL]];

within the cellForRowAtIndexPath method:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"PersonCell"];

    if (cell == nil){
     cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"PersonCell"] autorelease];
    }
    Person *person = [[Person alloc] initWithUserName:[people objectAtIndex:indexPath.row]];

    cell.imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:person.imageURL]];

    cell.textLabel.text = [people objectAtIndex:indexPath.row];

    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

    [person release];

    return cell;
}

And here is the relevant method from person.m

- (NSURL*) imageURL
{
    return [NSURL URLWithString:[userInfo valueForKey:@"profile_image_url"]];
}

EDIT: added init method:

- (id)initWithUserName:(NSString *)user{

    userName = [user copy];
    userInfo = [[TwitterHelper fetchInfoForUsername:userName] retain]; 
    updates = [[TwitterHelper fetchTimelineForUsername:userName] retain];

    return self;
}
+2  A: 

Only thing i can think of here that might be causing the leak is that you might be retaining the imageURL in your person class and dont have a release in its dealloc method. So when you are releasing person, it is leaking the imageURL property.

Daniel
my person.h contains @property (readonly) NSURL *imageURL;
Jason
and imageURL is synthesized
Jason
and i believe you should include a [imageURL release] in its dealloc
Daniel
the property retains the imageURL and when you release the person class it should also call release on its retained properties, which usually happens i n dealloc
Daniel
the dealloc method of the person class contains [imageURL release] and the same leak continues, any other suggestions?
Jason
its for sure that line?
Daniel
i mean the code looks ok, the only method in there that might be the culprit is initWithUserName, maybe post the code for that if you can
Daniel
initWithUserName has been added
Jason
+1  A: 

Try splitting the line and testing again. It might give you some insight.

NSURL *imgURL = person.imageURL;
NSData *imgData = [NSData dataWithContentsOfURL:imgURL]
cell.imageView.image = [UIImage imageWithData: imgData];

And you can comment the latter ones to see if the first one causes leaks.

Do you know how big the leak is? Is it image sized or URL sized?

mahboudz
The leak is 32 bytes and when I split it out Instruments tells me that NSData *imgData = [NSData dataWithContentsOfURL:imgURL] is the source of the leak.
Jason
I'm thinking that the 32 bytes is the right size for a short URL string. Maybe somehow person.imageURL is being retaining and never autoreleases... Check [imgURL retainCount].
mahboudz
NSURL *imgURL = person.imageURL; NSLog(@"retain count: %i", [imgURL retainCount]); NSData *imgData = [NSData dataWithContentsOfURL:imgURL]; NSLog(@"retain count: %i", [imgURL retainCount]);output is 1 then 9
Jason
+1  A: 

UIImage does a lot of caching. It may be appearing to leak if UIImage is holding a cache of the image.

Peter N Lewis
+1  A: 

do you have a dealloc for Person?

Naturally these three lines are a leak if you're not releasing then in dealloc:

userName = [user copy];
userInfo = [[TwitterHelper fetchInfoForUsername:userName] retain];  
updates = [[TwitterHelper fetchTimelineForUsername:userName] retain];
Raymond W
A: 

This may be related to autoreleasing.

Constructors like [NSData dataWithContentsOfURL:...] in Cocoa are automatically autoreleased. That call is the equivalent of [[[NSData alloc] initWithContentsOfURL:...] autorelease]. This may have something to do with it.

Matt Moriarity