我有一个由2个静态方法组成的CoreDataHelper静态类。我通过Clang运行我的项目并没有发现任何泄漏,但是通过Instruments运行显示泄漏,看起来它与CoreData有关。我对objective-c中的内存管理有基本知识,我相信我遵守规则。但是,我也认为我的代码更有可能出现问题,而不是Apple的CoreData堆栈中的错误。我正在运行最新的Snow Leopard,iPhone SDK 3.1,XCode 3.2。
stack trace:
17 UIKit 528 Bytes -[UIApplication _run]
16 UIKit 64 Bytes -[UIApplication sendEvent:]
15 UIKit 64 Bytes -[UIApplication handleEvent:withNewEvent:]
14 UIKit 64 Bytes -[UIApplication _runWithURL:sourceBundleID:]
13 UIKit 16 Bytes -[UIApplication _performInitializationWithURL:sourceBundleID:]
12 helm 16 Bytes -[helmAppDelegate applicationDidFinishLaunching:] Classes/helmAppDelegate.m:113
11 helm 16 Bytes +[CoreDataHelper entityWithUIDexists:::] Classes/CoreDataHelper.m:50
10 helm 16 Bytes +[CoreDataHelper searchObjectsInContextCopy:::::] Classes/CoreDataHelper.m:39
9 CoreData 16 Bytes -[NSManagedObjectContext executeFetchRequest:error:]
8 CoreData 16 Bytes -[NSPersistentStoreCoordinator(_NSInternalMethods) executeRequest:withContext:]
7 CoreData 16 Bytes -[NSSQLCore executeRequest:withContext:]
6 CoreData 16 Bytes -[NSSQLiteConnection connect]
5 CoreData 16 Bytes -[NSSQLConnection createSchema]
4 CoreData 16 Bytes -[NSSQLConnection createTablesForEntities:]
3 CoreData 16 Bytes -[NSSQLConnection createTableForEntity:]
2 CoreData 16 Bytes -[NSSQLAdapter newCreateTableStatementForEntity:]
1 Foundation 16 Bytes -[NSCFString appendFormat:]
0 CoreFoundation 16 Bytes -[NSObject respondsToSelector:]
的appdelegate:
BOOL b=[CoreDataHelper entityWithUIDexists:@"AddressBook" :context :[NSNumber numberWithInt:1]];
CoreDataHelper:
+(NSMutableArray *) searchObjectsInContextCopy: (NSString*) entityName : (NSManagedObjectContext *) managedObjectContext : (NSPredicate *) predicate : (NSString*) sortKey : (BOOL) sortAscending
{
NSLog(@"searchObjectsInContext");
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
// If a predicate was passed, pass it to the query
if(predicate != nil)
{
[request setPredicate:predicate];
}
// If a sort key was passed, use it for sorting.
if(sortKey != nil)
{
//NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:sortAscending selector: @selector(caseInsensitiveCompare:)];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:sortAscending selector: @selector(caseInsensitiveCompare:)];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortDescriptor release];
}
NSError *error;
NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
[request release];
return mutableFetchResults;
}
+(BOOL) entityWithUIDexists: (NSString *) entityName : (NSManagedObjectContext *) managedObjectContext : (NSNumber *) uid {
BOOL b;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(uid == %@)", uid];
NSMutableArray *ary=[self searchObjectsInContextCopy: entityName : managedObjectContext : predicate : nil : YES];
if(ary==nil) {
b=NO;
} else {
b=[ary count] >0 ? YES :NO;
}
[ary release];
return b;
}
答案 0 :(得分:1)
查看源代码,我发现了两件事。首先,初始化没有排序描述符的获取请求是错误的。引用SDK 3.1发行说明:
“当获取请求没有排序描述符时,NSFetchedResultsController不再崩溃。初始化没有排序描述符的NSFetchedResultsController仍然无效,但现在引发了一个正确的异常”
因此,您应该始终使用排序描述符初始化NSFetchedResultsController。 第二件事与你的泄漏有关。 executeFetchRequest:方法返回一个自动释放的NSArray。您正在使用mutableCopy方法,因此您返回一个由mutableCopy保留的对象。这基本上意味着您负责释放返回的对象。再次,引用mutableCopy方法文档:
“如果您正在使用托管内存(不是垃圾回收),则此方法在返回之前会保留新对象。但是,该方法的调用者负责释放返回的对象。”
答案 1 :(得分:0)
好的,我发现了一些有趣的东西。零排序描述符没有导致泄漏,它仍然存在,但也许我太早停止泄漏检测器。这是泄漏的方法。当我注释掉pragma标记时,16字节泄漏不会出现在Instruments中。为什么在方法中使用pragma标记会导致16字节泄漏?
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
NSString *databaseFilePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"Locations.sqlite"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if([fileManager fileExistsAtPath:databaseFilePath])
{
# pragma mark - flag to delete file
NSError *fMerror;
if (![fileManager removeItemAtPath:databaseFilePath error:&fMerror]) {
NSLog(@"persistentStoreCoordinator error %@, %@", fMerror, [fMerror userInfo]);
}
}
NSURL *storeUrl = [NSURL fileURLWithPath: databaseFilePath];
NSError *error;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {
NSLog(@"persistentStoreCoordinator error %@, %@", error, [error userInfo]); }
return persistentStoreCoordinator;
}