iOS 高效地从 Documents Dir 中解析大型 JSON

Posted

技术标签:

【中文标题】iOS 高效地从 Documents Dir 中解析大型 JSON【英文标题】:iOS Efficiently Parse Large JSONs from Documents Dir 【发布时间】:2013-02-01 21:59:03 【问题描述】:

当我加载我的应用程序时,我会下载大约 10-15 个 JSON 文件并将它们存储到我的应用程序文档目录中——其中一些文件的大小从几 KB 到 30MB 不等。

完成后,我需要从文档目录中获取它们中的每一个,转换为 NSDictionary,然后解析为 NSManagedObjects。

但是,当我使用下面的代码执行此操作时,当它通过每个 JSON 时,它似乎将它们保留在内存中,直到应用程序最终崩溃。 Instruments 在“泄漏”工具中没有显示任何内容,但我的应用程序在内存中保留了大量内容。

以下是获取 JSON 文件的代码:

更新

- (void)parseDownloadedFiles

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docDir = [paths objectAtIndex:0];
    docDir = [docDir stringByAppendingString:@"/jsons"];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;   
    NSArray *files = [fileManager contentsOfDirectoryAtPath:docDir error:&error];
    if (files == nil) 
        // error...
    

for (NSString *file in files) 


    NSString *fileName = [NSString stringWithFormat:@"%@/jsons/%@",
                          docDir, file];
    NSString *content = [[NSString alloc] initWithContentsOfFile:fileName
                                                    usedEncoding:nil
                                                           error:nil];

    NSDictionary *JSON =
    [NSJSONSerialization JSONObjectWithData: [content dataUsingEncoding:NSUTF8StringEncoding]
                                    options: NSJSONReadingMutableContainers
                                      error: &error];


       ...create my NSManagedObjects & store

       JSON = nil;
      

--

以下是我的分配:

--

深入了解第一个 Malloc 44.79 带来了以下问题:

-- 这是在上面代码的for循环中

NSLog 真的会导致这样的问题吗?

【问题讨论】:

【参考方案1】:

您应该将 @autoreleasepool 放在读取文件的那个循环中。对象在方法返回之前不会被释放,因此内存会在循环内堆积。

ARC 将通过自动释放对象来帮助您,但您需要它们更快地释放。

https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html

【讨论】:

我确实有一个封闭外循环的自动释放池——但是一旦我向内循环添加了一个,它的性能就会好得多。我仍然看到一些大约 50mb 的峰值,但在该文件完成处理后它会下降。我将在我的 JSON 上实现分页以减小它们的大小。谢谢【参考方案2】:

是的,您的 getContentFromFile... 方法正在返回一个保留的字符串。而且你永远不会在接收端释放它。

您需要在返回时自动释放字符串,或者在将其解析为 JSON 后显式释放。

(我认为 Analyzer 会发现这个。)

【讨论】:

这不是用 ARC 处理的吗? 我最终将该函数合并到第一个函数中,但我仍然看到相同的内存积累结果。我更新了上面的截图。谢谢! @RyanG - 这就像你没有启用 ARC。或者,也许正如 jsd 所暗示的那样,您没有返回空闲循环,您需要一个自动释放池。

以上是关于iOS 高效地从 Documents Dir 中解析大型 JSON的主要内容,如果未能解决你的问题,请参考以下文章

使用 System.IO.Packaging 在 c# 中解压缩 zip 文件

如何在iOS中解压缩异步方式的zip文件?

如何高效地从多个表中查询子记录?

更高效地从 qtableWidget 更新和插入 MYSQL 数据库

高效地从 H2 数据库中检索数据

如何尽可能高效地从 openCV 中获取 ORB 描述符?