1

我想在我的核心数据库中插入 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 字段)

4

3 回答 3

2
 object =(tblEntity *) [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context];


尝试类型转换对象,这可能会解决问题

于 2012-06-05T11:45:54.697 回答
2

我已经解决了这个问题。在调用 [self SaveItem] 之后;我用了

[context save];
[context reset];
[context save];

上下文中的所有 NSManagedObjects 都将被释放。完成该操作后,我可以添加任意数量的大对象

于 2012-06-06T08:55:02.847 回答
1

因为您在创建 NSManagedObject 时并不拥有它,所以即使在释放它之后(使用循环内包含的自动释放池时),它也可能被核心数据堆栈保留。

这可能会有所帮助:

  • 将 managedobjectContext 的撤消管理器设置为 nil:

    [context setUndoManager:nil];

  • 确保该对象的任何属性都不会保留在任何地方,因为这样托管对象将不会在循环内按时释放。

  • 确保在每个循环执行中添加一个自动释放池,而不是包装所有循环本身,类似于:

    for(i;i<n;i++) {
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
        [obj saveItem];
        [pool drain];
     }
    
  • 如果该对象属于 NSManagedObjects 的层次结构,那么您也需要释放该对象的所有者,以便从内存中释放该对象。

您可以在 CoreData 中查看苹果关于内存管理的文档。

警告:Apple 不建议将大对象(> 1MB)存储在 CoreData 中(请查看其他问题/答案。

于 2012-06-05T12:28:50.880 回答