我想在我的核心数据库中插入200条5Mb记录。但是当我保存NSManagedObject时,内存没有被释放(自动释放池没有帮助),插入30条记录后,我得到了内存警告,应用程序崩溃了。这是我的代码
- (void)SaveItem
{
NSString *entityName = kEntityName;
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = appDelegate.managedObjectContext;
NSEntityDescription *entityDesctiption = [NSEntityDescription
entityForName: entityName
inManagedObjectContext:context];
// check if town exists
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"id == %d", self.imageID];
NSFetchRequest *requestToCheckExistense = [[NSFetchRequest alloc] init];
[requestToCheckExistense setEntity:entityDesctiption];
[requestToCheckExistense setPredicate:predicate];
NSArray *objects = [context executeFetchRequest:requestToCheckExistense error:nil];
[requestToCheckExistense release];
if (objects == nil)
{
NSLog(@"there was an error");
}
NSManagedObject *object;
if ([objects count] > 0)
{
// edit item
object = [objects objectAtIndex:0];
}
else
{
// if object doesn't exist, find max id to imlement autoincrement
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesctiption];
request.propertiesToFetch = [NSArray arrayWithObjects: @"id", nil];
NSArray *allobjects = [context executeFetchRequest:request error:nil];
[request release];
NSInteger newID = 1;
if ([allobjects count] > 0)
{
NSNumber *maxID = [allobjects valueForKeyPath:@"@max.id"];
newID = [maxID intValue] + 1;
}
// write item
object = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context];
[object setValue:[NSNumber numberWithInt:newID] forKey:@"id"];
self.imageID = newID;
}
// fill NSManagedObject
// size of objNSData is about 5MB
NSMutableData *objNSData = [[DatabaseManager sharedDatabaseManager] encryptedDataFromImage:bigImage];
[object setValue:objNSData forKey:@"big"];
[context save:nil];
}
当我发表评论时
[object setValue:objNSData forKey:@"big"];
一切都很好。
我尝试将代码添加到@autoreleasepool中,但这没有帮助。 我知道,现在,当我将数据保存到数据库时,它仍然在iPhone RAM中。如何从这个内存中释放它?当我从数据库中获取一组托管对象时,它们不在RAM中(我可以轻松获得100个对象,每个对象都有5Mb字段)
答案 0 :(得分:2)
object =(tblEntity *) [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context];
尝试输入强制转换对象,这可能会解决问题
答案 1 :(得分:2)
我已经解决了这个问题。 调用[self SaveItem]之后; 我用了
[context save];
[context reset];
[context save];
将释放上下文中的所有NSManagedObjects。 在那个操作之后,我可以添加任意数量的大对象
答案 2 :(得分:1)
因为您在创建NSManagedObject时没有NSManagedObject,所以即使在释放它之后它也可能由核心数据堆栈保留(当使用循环中包含的autoreleasepool时)。
这可能有所帮助:
将managedobjectContext的撤消管理器设置为nil:
[context setUndoManager:nil];
确保该对象的任何属性都不会保留在任何位置,因为托管对象不会在循环内按时释放。
确保在每个循环执行中添加一个自动释放池,而不是包装所有循环本身,类似于:
for(i;i<n;i++) {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
[obj saveItem];
[pool drain];
}
如果该对象属于NSManagedObjects的层次结构,那么您也需要释放该对象的所有者,以便从内存中释放该对象。
您可以在CoreData中查看有关内存管理的apple's documentation。
警告:Apple不建议将大对象(> 1MB)存储在CoreData(Check this other question/answer.)中