0

我是一名新的 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 字段)

4

1 回答 1

3

在核心数据中存储图像(或大二进制值)不是一个好的选择。苹果建议不要这样做。这是有规则的。检查这个其他问题/答案。

如果你想从内存中取出对象,你需要删除你对它们的所有引用。如果您在紧密循环中执行“SaveItem”,则应将每个循环执行包装在自动释放池中,而不是循环本身。

从苹果文档中,这也可能是您的问题:

具有未决更改(插入、删除或更新)的托管对象由其上下文保留,直到其上下文被发送 save:、reset、rollback 或 dealloc 消息,或适当数量的撤消来撤消更改。与上下文关联的撤消管理器保留任何更改的托管对象。默认情况下,上下文的撤消管理器保留无限的撤消/重做堆栈。为了限制应用程序的内存占用,您应该确保在适当的时候清理(使用 removeAllActions)上下文的撤消堆栈。除非您保留上下文的撤消管理器,否则它会随其上下文一起被释放。

如果您不打算使用 Core Data 的撤消功能,您可以通过将上下文的撤消管理器设置为 nil 来减少应用程序的资源需求。这对于后台工作线程以及大型导入或批处理操作可能特别有益。

于 2012-06-05T11:34:01.143 回答