开发者

Memory leak after second viewing of tableview

I have two U开发者_如何学PythonITableViewControllers. I'm pushing to the second one and calling the following method in viewDidLoad.

The second time I dispose of this view and go back to the first view, I get a memory leak.

Instruments says the problem's on the last line of the following method.

- (void)fetchRecords {   

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:[NSEntityDescription entityForName:@"Articulation" inManagedObjectContext:[self managedObjectContext]]];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"articulationGroup == %@", selectedArticulationGroup];
    [request setPredicate:predicate];

    static NSArray *sortDescriptors = nil;
    if (!sortDescriptors)
        sortDescriptors = [[NSArray alloc] initWithObject:[[[NSSortDescriptor alloc] initWithKey:@"text" ascending:NO] autorelease]];
    [request setSortDescriptors:sortDescriptors];

    NSError *error = nil;
    NSArray *fetchResults = [managedObjectContext executeFetchRequest:request error:&error];
    if (!fetchResults)
        NSLog(@"no fetch results ArticulationsViewController, error %@", error);
    [request release];

    self.articulationsArray = [NSMutableArray arrayWithArray:fetchResults];

}

I've got no idea... going to bed :'(


For one thing, you're leaking your sortDescriptors array if you take the allocation branch. <soapbox> I strongly recommend you use curly braces around all if/else blocks even if they only have one line - these bugs are very difficult to find after the fact</soapbox>

Please post your dealloc method and the ivar declarations.


Well, I notice two things which might be correct but I wanted to ask about anyway.

First of all, ur asking in the if statement: if (!fetchResults). That would mean fetchResults possibly doesn't exist. Still, you try to initialize an array with that.

Secondly, I don't know how you allocated articulationsArray, but does changing the line into self.articulationsArray = [[NSMutableArray alloc] initWithArray:fetchResults]] have any effect?


Why is your sortDescriptors array static? Typically, you would do something like this:

NSSortDescriptor *textSort = [[NSSortDescriptor alloc] initWithKey:@"text" ascending:NO];

[fetchRequest setSortDescriptors:[NSArray arrayWithObject:textSort]];

[textSort release];

Also, after if (!fetchResults) you shouldn't save your array, but do something like this:

if (!fetchResults)
{
    NSLog(@"no fetch results ArticulationsViewController, error %@", error);
}
else
{
    NSMutableArray *articulationsArray_tmp = [fetchResults mutableCopy];
    self.articulationsArray = articulationsArray_tmp;
    [articulationsArray_tmp release];
}

[request release];

Also note how you could set the articulationsArray differently. One should always be careful with these NSMutableArrays ... :)


This block is completely unnecessary and it is dangerous:

static NSArray *sortDescriptors = nil;
if (!sortDescriptors)
    sortDescriptors = [[NSArray alloc] initWithObject:[[[NSSortDescriptor alloc] initWithKey:@"text" ascending:NO] autorelease]];
[request setSortDescriptors:sortDescriptors];

Any static object is dangerous to memory and you use them only in special cases. Why nail an array with only a local scope to a specific address/block? All this can be replaced with one line:

[request setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortWithKey:@"text" ascending:NO]]];

... and its done.

This line is probably unnecessary and likely to cause problems later:

self.articulationsArray = [NSMutableArray arrayWithArray:fetchResults];

Why would you need a mutable array of fetched objects? You can't really add or remove anything from the array directly while maintaining your graph integrity without refetching.

Just:

self.articulationsArray = fetchResults;

will work fine for most cases.

The more objects you create, the more chances for a leak you create. Keep things as simple as possible.


Well... I feel like a goose.

When I popped back to my first tableViewController, I wasn't releasing articulationsArray.

I was using

- (void)viewDidUnload {
    [self.articulationsArray release];
}

When I should have been using:

-(void)viewDidDisappear:(BOOL)animated {
    [self.articulationsArray release];
}

ViewDidUnload, was never being called.

Thanks for your help everyone.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜