解析JSON和创建NSManagedObjects时消耗大量内存

时间:2013-08-27 13:19:44

标签: ios objective-c json memory-management didreceivememorywarning

我正在解析一个大约53 MB的iPad上的JSON文件。解析工作正常,我正在使用Yajlparser这是一个SAX解析器,并设置如下:

    NSData *data = [NSData dataWithContentsOfFile:path options:NSDataReadingMappedAlways|NSDataReadingUncached error:&parseError];
    YAJLParser *parser = [[YAJLParser alloc] init];
    parser.delegate = self;
    [parser parse:data];

到目前为止一切正常,但JSON文件变大了,现在我突然在iPad 2上遇到内存警告。它收到4个内存警告,然后崩溃。在iPad 3上,它可以完美运行,没有任何内存警告。

我已经开始使用Instruments进行分析并发现了很多CFNumber分配(我已经在几分钟之后停止了仪器,我之前运行它直到崩溃并且CFNumber事件大约为60 mb或更多)。

CFNumber allocations

打开CFNumber详细信息后,它显示了一个巨大的分配列表。其中一个向我展示了以下内容:

CFNumber alloc 1

另一个在这里:

CFNumber alloc 2

那么我做错了什么?那个数字(例如最后一张图片中的72.8%)代表什么?我正在使用ARC,所以我没有做任何发布或保留等等。

感谢您的帮助。 干杯

编辑:我已经在这里询问了如何解析这些大文件的问题:iPad - Parsing an extremely huge json - File (between 50 and 100 mb)
所以解析本身似乎没问题。

2 个答案:

答案 0 :(得分:5)

请参阅Efficiently Importing Data上的Apple核心数据文档,特别是“减少峰值内存占用”。

您需要确保一次在内存中没有太多新实体,这包括在解析数据时定期保存和重置上下文,以及使用自动释放池。

一般的sudo代码是这样的:

while (there is new data) {
    @autoreleasepool {
        importAnItem();
        if (we have imported more than 100 items) {
            [context save:...];
            [context reset];
        }
    }
}

所以基本上,在主循环周围放置一个自动释放池或解析代码。计算已创建的NSManagedObject个实例数,并定期保存并重置托管对象上下文以刷新这些内存不足。这应该可以减少你的内存占用。数字100是任意的,您可能希望尝试使用不同的值。

因为您要保存每个批次的上下文,所以您可能希望导入商店的临时副本,以防出现问题并让您进行部分导入。一切都完成后,您可以覆盖原始商店。

答案 1 :(得分:1)

尝试在执行一定量的插入操作后使用[self.managedObjectContext refreshObject:obj refreshChanges:NO]。这会将NSManagedObjects变成错误并释放一些内存。

Apple Docs on provided methods