iOS:如何在操作大型NSString实例时避免自动释放的副本?

Bry*_*ace 7 cocoa-touch memory-management autorelease ios

我在iOS应用程序中有一个场景,操作一个非常大的NSString实例(一个HTTP响应,超过11MB)导致多个大型中介一次在内存中,因为我调用的SDK方法返回新的自动释放实例.在这里采取的最佳方法是什么?

例如,假设这largeString是一个自动释放的NSString实例:

NSArray *partsOfLargeString = [largeString componentsSeparatedByString:separator];

for (NSString *part in partsOfLargeString) {
    NSString *trimmedPart = [part stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

    NSData *data = [trimmedPart dataUsingEncoding:NSUTF8StringEncoding];
}
Run Code Online (Sandbox Code Playgroud)

如果有非自动释放等同这将是巨大的componentsSeparatedByStringstringByTrimmingCharactersInSet,但我不希望这些实施自己.

据我所知,没有办法"强制"释放已经添加到自动释放池中的对象.我知道我可以在这里创建和使用我自己的自动释放池,但我想要非常精细,并且围绕单个语句自动释放池肯定不是一个非常可扩展的方法.

任何建议都非常感谢.

小智 2

正如 Bill 所说,I\xe2\x80\x99d 首先尝试为每个循环迭代建立一个自动释放池,例如:

\n\n
for (NSString *part in partsOfLargeString) {\n    NSAutoreleasePool *pool = [NSAutoreleasePool new];\n\n    NSString *trimmedPart = [part stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];\n    NSData *data = [trimmedPart dataUsingEncoding:NSUTF8StringEncoding];\n    \xe2\x80\xa6\n\n    [pool drain];\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者,如果您\xe2\x80\x99正在使用足够新的编译器:

\n\n
for (NSString *part in partsOfLargeString) {\n    @autoreleasepool {\n        NSString *trimmedPart = [part stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];\n        NSData *data = [trimmedPart dataUsingEncoding:NSUTF8StringEncoding];\n        \xe2\x80\xa6\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果 \xe2\x80\x99s 仍然不可接受,并且您确实需要以更细粒度的方式释放对象,则可以使用类似以下内容的方法:

\n\n
static inline __attribute__((ns_returns_retained))\nid BICreateDrainedPoolObject(id (^expression)(void)) {\n    NSAutoreleasePool *pool = [NSAutoreleasePool new];\n    id object = expression();\n    [object retain];\n    [pool drain];\n    return object;\n}\n\n#define BIOBJ(expression) BICreateDrainedPoolObject(^{return (expression);})\n
Run Code Online (Sandbox Code Playgroud)\n\n

它评估表达式,保留其结果,释放任何辅助自动释放对象并返回结果;进而:

\n\n
for (NSString *part in partsOfLargeString) {\n    NSAutoreleasePool *pool = [NSAutoreleasePool new];\n\n    NSString *trimmedPart = BIOBJ([part stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]);\n    NSData *data = BIOBJ([trimmedPart dataUsingEncoding:NSUTF8StringEncoding]);\n    [trimmedPart release];\n\n    // do something with data\n    [data release];\n\n    \xe2\x80\xa6\n\n    [pool drain];\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

请注意,由于该函数返回一个保留的对象,因此您\xe2\x80\x99有责任释放它。您\xe2\x80\x99将可以控制何时执行此操作。

\n\n

请随意为函数和宏选择更好的名称。可能有一些应该处理的极端情况,但它应该适用于您的特定示例。欢迎提出建议!

\n