0

我一直在做一些测试,我的一个需求是从不同的 xml 文件中读取数据并将其堆叠在一个文件中。虽然我已经设法做到这一点,但该任务的内存消耗似乎相当大,iphone模拟器甚至没有发出内存警告,但我认为真正的 iPhone 不会容忍这一点(我没有一个在这里尝试的设备,所以我主要是从我读过的内容中推测)。
(主要部分)代码如下:

Boolean success = [fileManager createFileAtPath:documentsPath contents:nil attributes:nil];
[fileManager release];

if (success) {
    NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:documentsPath];
    for (int i = 0; i < 100; i++) {

        NSString *path = [[NSBundle mainBundle] pathForResource:@"mensagem_de_arquivo" 
                                                         ofType:@"xml"];
        NSData *data = [NSData dataWithContentsOfFile:path];
        GDataXMLDocument *xml = [[GDataXMLDocument alloc] initWithData:data options:0 error:nil];
        NSArray *tokens = [xml nodesForXPath:@"//message/data" error:nil];
        if (tokens.count > 0) {
            GDataXMLElement *token = (GDataXMLElement *)[tokens objectAtIndex:0];
            [fileHandle writeData:[[token stringValue] dataUsingEncoding:NSASCIIStringEncoding]];
        }
        [xml release];
    }

使用“构建和分析”命令没有给我任何泄漏或任何东西,并且代码在构建时不会发出警告,但内存消耗仍然在 50 到 70mb 之间(仅考虑实时字节,总体而言它几乎翻了一番)。
这个想法显然不是读取同一个文件的 100 次,但作为测试数据,它已经足够了,因为代码必须从 xml 文件中读取内容并按照接收顺序将它们发送到文件中。

有什么方法可以在分配新对象之前强制释放一些临时对象,我可以尝试重用一些变量吗?任何可以帮助我控制它的想法都非常受欢迎。

编辑- 只是为了让事情变得更有趣:最好保留一个解析器来读写,最好是坚持使用 GDataXML,或者,如果需要更改,使用 KissXML、TinyXML或 libxml - DOM,它们似乎都占用了更多内存,如此所述,因此如果有一种方法可以强制释放内存,那将是最好的。

提前致谢 :)

4

2 回答 2

1

实际上,这是一个非常简单的解决方案。

我所要做的就是实例化一个 AutoReleasePool 并在循环结束时将其排空。
像这样:

for (int i = 0; i < 100; i++) {
    NSAutoReleasePool *pool = [[NSAutoReleasePool alloc] init];
    //... do everything I've done before...
    [pool drain];
}

这迫使释放标记为在 for 中实例化的 autorelease 的对象,正如预期的那样,它们在结束后才被释放,而不会干扰其他所有内容,因此没有对象在它们应该被释放之前被释放。
在循环过程中,内存消耗从惊人的 60 ~ 80mb 下降到 1.6mb,然后又回到相同的 600kb(这是一个虚拟应用程序)。

我仍然会暂时保留这个问题,以防有人有更好的主意,但就目前而言,这似乎就是这样:)

于 2010-08-13T20:39:12.663 回答
0

是的,您通过将其全部读入 NSData,然后将其解析为 GDataXMLDocument 中的 DOM,将其“加倍”。如果您希望像这样遍历大量 XML 数据、循环多个文件等,那么您应该考虑改为基于 SAX 的解析,并将其直接从文件中流式传输,而不是将其预加载到 NSData 中。这样,您就不必“释放临时对象”,因为您只会在解析时提取您需要的信息。

于 2010-08-11T21:28:51.417 回答