Эндрю ответил на ваш главный вопрос, что, да, ваш бассейн AutorElease будет истощен на каждом цикле основного цикла пробега. Таким образом, любые объекты авторелиазы, созданные в viewDidLoad
может быстро стать сливами, когда вы уступите обратно в основной цикл пробега. Они, безусловно, не будут сохранены «до прекращения приложения».
Но мы должны быть осторожны: вы ясно предполагаете, что эти объекты добавляются в пул авторелиаза. Несколько предостережений к этому предположению:
В прошлом (и все еще требуется для взаимодействия ARC-MRC), когда возвращается объекты из методов, имена которых не начались с alloc
, new
, copy
, или же mutableCopy
, Эти объекты будут авторелизировать объекты, сделкивались только в том случае, когда пул авторелиазы был осушен (т. Е. Когда вы обратно обратно в петлю пробега).
Но ARC стала умнее минимизировать потребность в бассейнах авторелиазы (см. http://rentzsch.tumblr.com/post/75082194868/arcs-fast-autorelease, который обсуждает callerAcceptsFastAutorelease
, теперь называется callerAcceptsOptimizedReturn
призван prepareOptimizedReturn
), так что вы часто не увидите этого autorelease
поведение. Таким образом, если и библиотека, и вызывающий абонент используют ARC, объекты не могут быть помещены в бассейн AutoRealease, а 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 объектов в пул AutorElease, который будет осуществляться только тогда, когда я уступлю обратно в цикл пробега:
В этом случае вы можете использовать бассейн с авторелиазом, чтобы минимизировать высокий знак воды:
@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
Итог, с дугой, не всегда очевидно, когда он использовал объект авторелиазы и когда он явно высвобождает его, когда переменная выпадает из области. Вы всегда можете подтвердить это, изучив поведение в инструментах.
Кроме того, я буду насторожен NSString
Класс, так как он был высоко оптимизирован и не всегда соответствует стандартной практике управления памятью.