CoreData:释放ManagedObject

时间:2010-07-10 08:50:32

标签: iphone objective-c sqlite nsmanagedobject core-data

我在iOS 4 iPhone应用程序中使用CoreData(使用SQLite作为商店)来存储我最初从xml文件中检索的数据。我的数据模型包含超过15个实体,我担心内存消耗,因为我看到CoreData在内存中创建所有NSManagedObject来表示我的数据模型的对象图。 我使用基于SAX libxml2的解析器解析xml文件,并尝试将每个'agglomerate set'实体存储在chunk中,但是我想在插入这个agglomerate并保存托管上下文之后释放每个managedobject,按顺序为下一个聚集体节省内存。 我看到我必须使用refreshObject:mergeChanges:来抵消每个对象在通过关系(如数据模型中设计)与其他对象关联时收到的多个保留​​。我在保存上下文之后这样做,但接下来当我尝试在商店中再次查找尝试获取我插入的内容之前它没有返回任何内容。 我错过了什么吗?

3 个答案:

答案 0 :(得分:2)

如果您只是导入(例如,您不需要将插入的对象保持显示给用户等等),则可以在保存后使用[moc reset]。所以算法看起来像这样:

NSManagedObjectContext* moc = ...;
while ([xmlData hasMoreObjects]) {
    // Create e.g. 500 objects and insert them into the managed object context
    NSError* error = nil;
    if (![moc save:&error]) {
        // handle the error
    }
    [moc reset]; // Here the inserted objects get released in the core data stack
}

重置托管对象上下文与刷新每个对象(就像之前所做的那样)相同。另外你应该考虑使用[[NSManagedObject alloc] initWithEntity:insertIntoManagedObjectContext:]代替NSEntityDescription上的便捷方法,因为你可以在你不再需要它们之后立即释放它们,并且它们不会留在内存中直到自动释放池得到澄清。

查看核心数据编程指南,因为它包含一个以高效导入数据为中心的整个部分,以及一个关于使用核心数据进行内存管理的部分。

答案 1 :(得分:1)

您无法直接/手动管理托管对象的内存,因为上下文已控制对象的生命周期以维护图形完整性。

如果您可以在离散块中处理导入,请在每个块之后保存上下文,然后按:

[context refreshObject:theObject mergeChanges:NO]

...它会将新保存的对象转换为错误,因此占用的内存非常少。

您只需要设置关系的错误,因此在前一个块中处理的对象仍可用于在当前块中的关系中设置。

只要有可能,我会在一次传递中创建对象,保存它们,将它们转换为错误,然后在下一次传递中设置关系。如果您有必要的关系,这并不总是实用的。

如果您还没有这样做,可能需要查看核心数据编程指南:Efficiently Importing Data

答案 2 :(得分:0)

我认为你必须为每次改变都做到这一点

NSManagedObjectContext *moc;
NSError *error;
[moc save:&error];

否则将被丢弃