Andrew 回答了您的主要问题,是的,您的自动释放池将在主运行循环的每个循环中耗尽。因此,当您返回主运行循环时,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 类时,我会小心不要得出太多通用的内存管理结论,因为它已经过高度优化,并不总是符合标准的内存管理实践。