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

我在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];
}

如果componentsSeparatedByString或stringByTrimmingCharactersInSet有非自动释放的等价物会很棒,但我不打算自己实现这些.

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

任何建议都非常感谢.

解决方法

正如Bill所说,我首先尝试为每个循环迭代设置一个自动释放池,例如:
for (Nsstring *part in partsOfLargeString) {
    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    Nsstring *trimmedPart = [part stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    NSData *data = [trimmedPart dataUsingEncoding:NSUTF8StringEncoding];
    …

    [pool drain];
}

或者,如果您使用的是最近的编译器:

for (Nsstring *part in partsOfLargeString) {
    @autoreleasepool {
        Nsstring *trimmedPart = [part stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        NSData *data = [trimmedPart dataUsingEncoding:NSUTF8StringEncoding];
        …
    }
}

如果仍然无法接受并且您确实需要以更精细的方式发布对象,则可以使用以下内容

static inline __attribute__((ns_returns_retained))
id BICreateDrainedPoolObject(id (^expression)(void)) {
    NSAutoreleasePool *pool = [NSAutoreleasePool new];
    id object = expression();
    [object retain];
    [pool drain];
    return object;
}

#define BIOBJ(expression) BICreateDrainedPoolObject(^{return (expression);})

它会计算表达式,保留其结果,释放任何辅助自动释放的对象并返回结果;然后:

for (Nsstring *part in partsOfLargeString) {
    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    Nsstring *trimmedPart = BIOBJ([part stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]);
    NSData *data = BIOBJ([trimmedPart dataUsingEncoding:NSUTF8StringEncoding]);
    [trimmedPart release];

    // do something with data
    [data release];

    …

    [pool drain];
}

请注意,由于函数返回一个保留对象,因此您负责释放它.你可以控制何时这样做.

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

相关文章

UITabBarController 是 iOS 中用于管理和显示选项卡界面的一...
UITableView的重用机制避免了频繁创建和销毁单元格的开销,使...
Objective-C中,类的实例变量(instance variables)和属性(...
从内存管理的角度来看,block可以作为方法的传入参数是因为b...
WKWebView 是 iOS 开发中用于显示网页内容的组件,它是在 iO...
OC中常用的多线程编程技术: 1. NSThread NSThread是Objecti...