安德鲁回答了您的主要问题,是的,您的自动释放池将在主运行循环的每个循环中耗尽。viewDidLoad
因此,当您返回到主运行循环时,其中创建的任何自动释放对象都可能会立即耗尽。它们肯定不会保留“直到应用程序终止”。
但我们应该小心:您显然假设这些对象被添加到自动释放池中。对这个假设的一些警告:
在过去(并且仍然需要 ARC-MRC 互操作性),当从名称不以alloc
、new
、copy
或开头的方法返回对象时mutableCopy
,这些对象将自动释放对象,仅在自动释放池耗尽时(即当您回到运行循环)。
但是 ARC 在最大限度地减少对自动释放池的需求方面变得更加聪明(参见http://rentzsch.tumblr.com/post/75082194868/arcs-fast-autorelease,其中讨论callerAcceptsFastAutorelease
,现在称为callerAcceptsOptimizedReturn
由 调用prepareOptimizedReturn
),所以你通常不会看到这个autorelease
行为。因此,如果库和调用者都使用 ARC,则对象可能不会放入自动释放池中,但如果不需要,ARC 会巧妙地立即释放它们。
对于当代 ARC 项目,通常不需要自动释放池。但是在某些特殊情况下,仍然可以从使用自动释放池中受益。我将在下面概述其中一种情况。
考虑以下代码:
#import "ViewController.h"
#import <sys/kdebug_signpost.h>
typedef enum : NSUInteger {
InnerLoop = 1,
MainLoop = 2
} MySignPostCodes;
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"png"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
kdebug_signpost_start(MainLoop, 0, 0, 0, 1);
for (int j = 0; j < 500; i++) {
NSData *data = [NSData dataWithContentsOfURL:fileURL];
UIImage *image = [[UIImage alloc] initWithData:data];
NSLog(@"%p", NSStringFromCGSize(image.size)); // so it's not optimized out
[NSThread sleepForTimeInterval:0.01];
}
kdebug_signpost_end(MainLoop, 0, 0, 0, 1);
});
}
@end
以下代码将向自动释放池中添加 500,000 个对象,这些对象只有在我返回到运行循环时才会被耗尽:
在这种情况下,您可以使用自动释放池来最小化高水位线:
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"png"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
kdebug_signpost_start(MainLoop, 0, 0, 0, 1);
for (int j = 0; j < 5; j++) {
@autoreleasepool {
kdebug_signpost_start(InnerLoop, 0, 0, 0, 2);
for (long i = 0; i < 100; i++) {
NSData *data = [NSData dataWithContentsOfURL:fileURL];
UIImage *image = [[UIImage alloc] initWithData:data];
NSLog(@"%p", NSStringFromCGSize(image.size)); // so it's not optimized out
[NSThread sleepForTimeInterval:0.01];
}
kdebug_signpost_end(InnerLoop, 0, 0, 0, 2);
}
}
kdebug_signpost_end(MainLoop, 0, 0, 0, 1);
});
}
@end
最重要的是,对于 ARC,当它使用自动释放对象以及在变量超出范围时显式释放它时并不总是很明显。您始终可以通过检查 Instruments 中的行为来确认这一点。
顺便说一句,在使用该类时,我对得出太多通用内存管理结论持谨慎态度NSString
,因为它已经过高度优化,并不总是符合标准的内存管理实践。