我是一名新的iOS开发人员。希望得到帮助。 我希望能够创建许多NSManagedObjects。一个NSManagedObject的字段大小约为5Mb。我无法在iPhone内存中保存如此大量的内存。我想将它保存在数据库中。但是当我保存NSManagedObject时,它仍然在内存中,因为当我保存大约20个对象时,我收到内存警告并且应用程序崩溃。 这是我的代码
- (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];
}
当我尝试调用[self SaveItem] 20次时,应用程序崩溃并显示内存警告。当我发表评论时
[object setValue:objNSData forKey:@"big"];
一切都很好。
我尝试将代码添加到@autoreleasepool,但这没有帮助。
我知道,现在,当我将数据保存到数据库时,它仍然在iPhone内存中。如何从这个内存中释放它? 当我得到一组托管对象时,它们不在内存中(我可以轻松获得100个对象,每个对象都有5Mb字段)
答案 0 :(得分:3)
在核心数据中存储图像(或大二进制值)不是一个好选择。 Apple建议不要这样做。有规则。 Check this other question/answer.
如果要使对象内存不足,则需要删除对它们的所有引用。如果您在紧密循环中执行“SaveItem”,则应将每个循环执行包装在自动释放池中,而不是循环本身。
从苹果文档来看,这也可能是你的问题:
具有挂起更改(插入,删除或更新)的托管对象由其上下文保留,直到其上下文发送save:,reset,rollback或dealloc消息,或者要撤消的相应数量的undos改变。 与上下文关联的撤消管理器保留任何已更改的受管对象。默认情况下,上下文的撤消管理器保留无限制的撤消/重做堆栈。要限制应用程序的内存占用,应确保在适当的时候擦除(使用removeAllActions)上下文的撤消堆栈。除非您保留上下文的撤消管理器,否则它将根据其上下文取消分配。
如果您不打算使用Core Data的撤消功能,可以通过将上下文的撤消管理器设置为nil来减少应用程序的资源需求。这对后台工作线程以及大型导入或批量操作尤其有用。