アンドリューは、メインの実行ループのサイクルごとに自動解放プールが排出されるという主な質問に答えました。viewDidLoad
そのため、メインの実行ループに戻ると、作成された autorelease オブジェクトはすぐに排出される可能性があります。それらは確かに「アプリケーションが終了するまで」保持されません。
ただし、注意が必要です。これらのオブジェクトが自動解放プールに追加されていると想定していることは明らかです。この仮定にはいくつかの注意事項があります。
alloc
以前は (現在も ARC-MRC の相互運用性のために必要)、名前が、new
、copy
、またはで始まらないメソッドからオブジェクトを返す場合mutableCopy
、それらのオブジェクトはオブジェクトを自動解放し、自動解放プールが空になったとき (つまり、実行ループに戻ります)。
しかし、ARC は、自動解放プールの必要性を最小限に抑えることについてより賢くなりました ( http://rentzsch.tumblr.com/post/75082194868/arcs-fast-autoreleasecallerAcceptsFastAutorelease
を参照してください。これは、現在callerAcceptsOptimizedReturn
呼び出されている について説明しprepareOptimizedReturn
ています)。autorelease
行動。そのため、ライブラリと呼び出し元の両方が ARC を使用している場合、オブジェクトは自動解放プールに配置されない可能性がありますが、不要な場合は ARC が巧妙にそれらをすぐに解放します。
現在の ARC プロジェクトでは、通常、自動リリース プールは必要ありません。ただし、特定の特殊なケースでは、自動解放プールを使用することでメリットが得られます。以下に、そのケースの 1 つを概説します。
次のコードを検討してください。
#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 では、いつ autorelease オブジェクトを使用したか、および変数がスコープ外になったときにそれを明示的に解放したかが常に明らかであるとは限りません。これは、Instruments の動作を調べることでいつでも確認できます。
余談ですが、このNSString
クラスは高度に最適化されており、標準のメモリ管理慣行に常に準拠しているわけではないため、このクラスを使用する際に一般的なメモリ管理の結論を出しすぎることには注意が必要です。