Начнем с retain
и release
; autorelease
действительно просто частный случай, если вы понимаете основные концепции.
В Какао каждый объект отслеживает, сколько раз на него ссылаются (в частности, NSObject
базовый класс реализует это). Вызывая retain
объект, вы сообщаете ему, что хотите увеличить его счетчик ссылок на единицу. Вызывая release
, вы сообщаете объекту, что отпускаете его, и его счетчик ссылок уменьшается. Если после вызова release
счетчик ссылок теперь равен нулю, то память этого объекта освобождается системой.
В основном это отличается от этого malloc
и free
заключается в том, что любому данному объекту не нужно беспокоиться о сбое других частей системы, потому что вы освободили память, которую они использовали. Предполагая, что все подыгрывают и сохраняют / освобождают в соответствии с правилами, когда один фрагмент кода сохраняет, а затем освобождает объект, любой другой фрагмент кода, также ссылающийся на объект, не будет затронут.
Иногда может сбивать с толку знание обстоятельств, при которых вам следует позвонить retain
и release
. Мое общее практическое правило состоит в том, что если я хочу удерживать объект в течение некоторого времени (например, если это переменная-член в классе), то мне нужно убедиться, что счетчик ссылок объекта знает обо мне. Как описано выше, счетчик ссылок на объект увеличивается при вызове retain
. По соглашению, он также увеличивается (на самом деле устанавливается в 1), когда объект создается с помощью метода "init". В любом из этих случаев я должен вызвать release
объект, когда я закончу с ним. Если я этого не сделаю, произойдет утечка памяти.
Пример создания объекта:
NSString* s = [[NSString alloc] init]; // Ref count is 1
[s retain]; // Ref count is 2 - silly
// to do this after init
[s release]; // Ref count is back to 1
[s release]; // Ref count is 0, object is freed
Теперь для autorelease
. Автозапуск используется как удобный (а иногда и необходимый) способ сообщить системе о необходимости освободить этот объект через некоторое время. С точки зрения сантехники, когда autorelease
вызывается, текущий поток NSAutoreleasePool
получает предупреждение о вызове. NSAutoreleasePool
Теперь знает , что когда - то он получает возможность (после текущей итерации цикла событий), он может позвонить release
на объекте. С нашей точки зрения, как программисты, он заботится о том release
, чтобы позвонить нам, так что нам не нужно (и на самом деле не следует).
Важно отметить, что (опять же, по соглашению) все методы класса создания объекта возвращают автоматически выпущенный объект. Например, в следующем примере переменная s имеет счетчик ссылок 1, но после завершения цикла событий она будет уничтожена.
NSString* s = [NSString stringWithString:@"Hello World"];
Если вы хотите закрепить эту строку, вам нужно будет вызвать ее retain
явно, а затем явно, release
когда вы закончите.
Рассмотрим следующий (очень надуманный) фрагмент кода, и вы увидите ситуацию, в которой autorelease
требуется:
- (NSString*)createHelloWorldString
{
NSString* s = [[NSString alloc] initWithString:@"Hello World"];
// Now what? We want to return s, but we've upped its reference count.
// The caller shouldn't be responsible for releasing it, since we're the
// ones that created it. If we call release, however, the reference
// count will hit zero and bad memory will be returned to the caller.
// The answer is to call autorelease before returning the string. By
// explicitly calling autorelease, we pass the responsibility for
// releasing the string on to the thread's NSAutoreleasePool, which will
// happen at some later time. The consequence is that the returned string
// will still be valid for the caller of this function.
return [s autorelease];
}
Я понимаю, что все это немного сбивает с толку, но в какой-то момент это щелкнет. Вот несколько справочных материалов, которые помогут вам начать работу:
- Введение Apple в управление памятью.
- Какао-программирование для Mac OS X (4-е издание) , Аарон Хиллегас - очень хорошо написанная книга с множеством отличных примеров. Он читается как учебник.
- Если вы действительно погружаетесь, вы можете отправиться на ранчо Big Nerd Ranch . Это учебный центр, которым управляет Аарон Хиллегас - автор упомянутой выше книги. Несколько лет назад я посетил там курс «Введение в какао», и это был отличный способ научиться.