Ток NSAutoreleasePool
делает и позаботится об освобождении при сливе.
IBAction
вызовы помещаются в NSAutoreleasePool
, который истощается после вызова.
Для всех вызовов, не относящихся к IBAction, применяется следующее:
Скажем, у вас есть следующие методы:
- (id)foo {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
SomeClass *bar = [self bar]; //bar still exists here
//do other stuff
//bar still exists here
//do other stuff
//bar still exists here
[pool drain]; //bar gets released right here!
//bar has been released
}
- (id)bar {
return [[[SomeClass alloc] init] autorelease]; //bar will still be around after the return
}
Рассмотрим другой сценарий:
- (void)foo {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//do other stuff
[self bar];
//do other stuff
[pool drain]; //the string from blee would be released right here;
}
- (void)bar {
[self baz];
}
- (void)baz {
NSString *string = [self blee];
}
- (id)blee {
return [NSString string]; //autoreleased
}
Как видите, автоматически освобожденный строковый объект даже не нужно было использовать или возвращать в область, в которой был создан пул.
NSAutoreleasePools существуют в стеке (по одному на поток), и автоматически выпущенные объекты становятся собственностью пула, который является самым верхним на момент вызова autorelease
.
Обновление:
Если вы имеете дело с узким циклом и хотите, чтобы объем памяти оставался умеренным, не замедляя цикл, подумайте над тем, чтобы сделать что-то подобное:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
for (NSUInteger i = 0; i < 1000000000; i++) {
[NSString stringWithString:@"foo"];
if (i % 1000 == 0) {
[pool drain];
pool = [[NSAutoreleasePool alloc] init];
}
}
[pool drain];
Однако NSAutoreleasePool
высоко оптимизирован, поэтому один пул на итерацию обычно не представляет большой проблемы.
Чтобы полностью понять, как работает NSAutoreleasePools, прочитайте эту отличную статью Майка Эша