iPhone NSCFString leaks in fetchRequest
In the following code:
- (NSMutableArray *) fetchNotesForGroup: (NSString *)groupName {
// Variables declaration
NSMutableArray *result;
NSFetchRequest *fetchRequest;
NSEntityDescription *entity;
NSSortDescriptor *sortDescriptor;
NSPredicate *searchPredicate;
NSErr开发者_高级运维or *error = nil;
// Creates the fetchRequest and executes it
fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
entity = [NSEntityDescription entityForName:@"Note" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"noteName" ascending:YES] autorelease];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[fetchRequest setReturnsDistinctResults:YES];
searchPredicate = [NSPredicate predicateWithFormat:@"categoryName like %@", groupName];
[fetchRequest setPredicate:searchPredicate];
[fetchRequest setPropertiesToFetch:[NSArray arrayWithObject:@"noteName"]];
result = [[managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];
// Variables release
return result;
}
... I Fetch notes for a given categoryName. When I'm running Instruments, it says that a NSCFString is leaking.
I know leaks are mean for iPhone developers... but I don't have any idea on how to plug this one.
Any clues? All help is welcome.
Thanks a lot!
Your problem is this:
result = [[managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];
// Variables release
return result;
mutableCopy
returns an owning reference (ie, an object with a +1 retain count), which you are responsible for (auto)releasing. You don't, and you then relinquish the reference, which means you've leaked the array.
Use return [result autorelease];
instead.
First of all, Instruments may not be always accurate.
It can report leaks on some special case, just because it don't see you are actually releasing the object elsewhere.
It's also possible that some parts of the CF have leaks.
What I can see in your code is that you are using auto-released objects.
You're temporary objects will have a long life-cycle.
What append if you release them explicitly instead, just before the method's return?
You are also returning a copy of an object.
You have to make sure that object is released at some point.
It may be much better to return an auto-released object, and let the calling method decide if the object should be retained.
Since you don't create any strings, the leaking string is most likely one of the strings that ends up inside the fetch request and it is most likely the fetch request that is actually leaking. (The call stack shown in Instruments should confirm this.)
I don't think you have an actual leak but by doing this:
fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
... you are allowing the fetchRequest to live beyond the scope where it was defined Instruments will interpret that as a leak.
Autorelease actually makes objects live longer than direct release because it causes objects to hang around until the outer autorelease pool is drained. For example, if you create object-B inside object-A and return it to object-C autoreleased, object-B will stay alive long after object-A has been deallocated even if object-C never retains it. (Although it will eventually die at an unpredictable moment.)
Autorelease is not a convenience method for retaining. It has a specific purpose of retaining objects that are being passed between other objects. If your not doing this, don't use autorelease.
If you do this:
fetchRequest = [[NSFetchRequest alloc] init];
// ...
[fetchRequest release];
... your leak will go away.
You might, however, want to do this:
return [result autorelease];
... to ensure that the result array lives long enough to be retained by another object.
精彩评论