我在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]; }
请注意,由于函数返回一个保留对象,因此您负责释放它.你可以控制何时这样做.