Andrew ответил на ваш главный вопрос: да, ваш пул авторефератов будет слит в каждом цикле основного цикла запуска. Таким образом, любые объекты авторекламы, созданные в viewDidLoad
, могут быстро разрядиться, когда вы возвращаетесь к основному циклу запуска. Они, конечно же, не будут сохранены «до окончания подачи заявления».
Но мы должны быть осторожны: вы явно предполагаете, что эти объекты добавляются в пул автоопределений. Несколько предостережений к этому предположению:
В прошлом (и по-прежнему необходимы для АРК-MRC взаимозаменяемости), при возврате объектов из методов, имена которых не начинаются с alloc
, new
, copy
или mutableCopy
, эти объекты будут авторезистентными объектами, освобожденными только тогда, когда пул авторесурсов был истощен (т. е. когда вы вернулись к циклу запуска).
Но ARC получил умнее о минимизации потребности в autorelease бассейнов (см 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
Следующий код добавит 500000 объектов в 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
Нижняя линия, с ARC, это не всегда очевидно, когда он используется объект autorelease и когда он явно освобождает его, когда переменная выходит из области видимости. Вы всегда можете подтвердить это, изучив поведение в Инструментах.
Как бы в стороне, я бы с осторожностью относился к выработке слишком большого объема общих соображений управления памятью при использовании класса NSString
, так как он был высоко оптимизирован и не всегда соответствует стандартным правилам управления памятью.
«Следующий код добавит 500 000 объектов в пул автообновлений, которые будут только слиты, когда я вернусь к циклу запуска». Возможно, ARC немедленно выпустит его, как и второй код, возможно, с оптимизацией, на. – newacct
Я выбрал [NSString stringWithFormat:], потому что я знаю, что возвращаемый объект вызвал авторекламу. Все это я знал ранее, за исключением пула вокруг каждого события, но спасибо за разъяснение. Надеюсь, это поможет кому-то другому, кто наткнулся на этот вопрос :) –
если 'object = nil' удаляет исходный объект из памяти, то, возможно,' object = [MyObject myObject] 'удаляет исходный объект из памяти. Почему он будет храниться в авторекладе в ARC? – stefanB