将长字符串保留在内存中的最佳方法是什么? (可可)

时间:2013-06-30 23:48:46

标签: objective-c cocoa

我有一个Cocoa程序正在编辑数百个(有时是数千个)第三方文件,我想创建一个日志类型的输出供最终用户查看(虽然我不需要像时间戳这样的东西)。目前我只是将字符串附加到插座:

@property (unsafe_unretained) IBOutlet NSTextView *finalText;
...
self.finalText.string = [self.finalText.string stringByAppendingFormat:@"Final results:\n"];

但效率极低。当我在700个文件上运行该代码并关闭上述代码(所有注释)时,执行上述代码需要4秒钟,上面的代码打开需要40秒才能创建必要的8,000行输出。哦,我是否提到Xcode说我的内存使用量在处理过程中达到了2GB以上?糟糕!

我明白我所做的事情效率低下,但我不知道提高效率的最佳方法。创建最终用户最终可以看到的8,000行文本的最佳方法是什么?像Lumberjack之类的东西会是最好的解决方案吗?

3 个答案:

答案 0 :(得分:1)

伐木工人非常适合伐木。此外,您应该使用NSMutableString来避免一次又一次地创建相同字符串的副本。

答案 1 :(得分:0)

[self.textView.textStorage appendAttributedString:...]

这将减少工作量。另外,将其包装在@autoreleasepool中以及时清理临时对象。

答案 2 :(得分:-1)

你应该用这个:

NSData *data = [[NSData alloc] initWithContentsOfURL:url];

使用300GB文件需要一到两毫秒,如果有足够的RAM可用,只会将整个文件加载到RAM中。如果没有足够的RAM可用,它将仅加载您实际读取的文件的部分,并且还可以启发式/预测性地读取操作系统认为您将要阅读的部分。

NSString是CFString的便利包装器。如果您下拉到较低级别的CFString API,您将能够编写代码,以便它使用较少的RAM(例如,通过部分解码大文件)。从文件中部分读取字符串很复杂,您需要了解UTF-8的工作原理,并确保不要在UTF-8序列的中途剪切数据。如果你能用NSString获得可接受的性能,我会尽量避免使用CFString。

此外,您是否有forwhile循环遍历所有文件?确保循环中有一个“autorelease”池:

NSArray *urls = <# An array of file URLs #>;
for (NSURL *url in urls) {

    @autoreleasepool {
        NSError *error;
        NSString *fileContents = [NSString stringWithContentsOfURL:url
                                         encoding:NSUTF8StringEncoding error:&error];
        /* Process the string, creating and autoreleasing more objects. */
    }
}

(来自http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html#//apple_ref/doc/uid/20000047-SW2