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

前端之家收集整理的这篇文章主要介绍了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];
}

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

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

猜你在找的iOS相关文章