【发布时间】:2011-09-17 03:47:54
【问题描述】:
在我的 Garbage Collected Mac 应用程序中,由于我使用了一个帮助函数来删除特定类型的所有核心数据实体,我的内存使用率非常高。函数如下,供参考:
- (void)deleteAllObjectsForEntity:(NSString *)entityDescription {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityDescription inManagedObjectContext:self];
[request setEntity:entity];
[request setIncludesPropertyValues:NO];
NSError *error = nil;
NSArray *items = [self executeFetchRequest:request error:&error];
[request release];
// Delete all objects
for (NSManagedObject *managedObject in items)
{
[self deleteObject:managedObject];
}
// Should probably check for errors here
[self save:&error];
[self reset];
// Suggest the garbage collector tries to tie up any loose ends
[[NSGarbageCollector defaultCollector] collectIfNeeded];
}
通过使用堆分析,我可以看到每次使用上述函数删除我的 FileRecord 实体的所有实例时,堆都会增长大约 50MB。似乎永远无法恢复的记忆。
通过使用-com.apple.CoreData.SQLDebug 1 启动参数,我可以看到大部分内存是由我的NSFetchRequest 期间触发的(许多)SELECT 语句引起的。似乎每次选择这些对象时,Core Data 都会触发错误(并因此分配内存)。显然我不需要触发这些错误,因为我随后将删除该对象。这是我的控制台输出示例:
CoreData: annotation: fault fulfilled from database for : 0x2002ed3e0 <x-coredata://17E6216A-C2FA-42A6-B8E4-5209CD1AB2CA/FileRecord/p117418>
CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZNORMALIZEDPATH, t0.ZSIZE, t0.ZFILENAME, t0.ZKIND, t0.ZNORMALIZEDFILENAME, t0.ZPATH FROM ZFILERECORD t0 WHERE t0.Z_PK = ?
无论我做什么,我都无法让这段记忆被放弃。如您所见,我保存然后重置我的 NSManagedObjectContext。此外,我向垃圾收集器暗示它可能会尝试收集任何滞留数据。
不幸的是,我正在使用现有的 Core Data 架构,因此无法设置诸如级联删除规则之类的任何内容。无论如何,我在这里做错了什么?
【问题讨论】:
-
为什么要继承 NSManagedObjectContext?
-
我没有继承 NSManagedObjectContext。我的 deleteAllObjectsForEntity 方法存在于一个类别中。
-
好吧,哈哈,我建议运行垃圾收集器工具,看看收集器在此操作期间实际尝试做什么。
-
您通常在此循环中删除多少对象?
-
@ndg 我知道这已经很久了,但是您找到解决方案了吗?我已经为此头疼了好几天。堆增加,如果我重复执行一段时间,我的应用程序会因内存警告而被杀死。
标签: cocoa core-data garbage-collection nsmanagedobject