ИМХО, какой путь «правильный», является вопросом предпочтения. Я не согласен с респондентами, которые выступают за то, чтобы не использовать autorelease
, но я предпочитаю использовать autorelease
, если для этого нет веских причин. Я перечислю свои причины, и вы сможете решить, соответствуют ли они вашему стилю программирования.
Как указал Чак, существует полугородская легенда о том, что использование пусков автоматического выпуска связано с некоторыми накладными расходами. Это не может быть дальше от истины, и это происходит из-за бесчисленных часов, проведенных с использованием Shark.app, чтобы выжать последний бит производительности из кода. Попытка оптимизировать это глубоко на «преждевременной оптимизации» территории. Если и только если Shark.app предоставит вам достоверные данные о том, что это может быть проблемой, если вы даже подумаете об этом.
Как отмечали другие, автоматически выпущенный объект "освобождается в какой-то более поздний момент". Это означает, что они задерживаются, забирая память, пока эта «точка отсчета» не перевернется. В «большинстве» случаев это находится в нижней части прохода обработки события, прежде чем цикл выполнения переходит в спящий режим до следующего события (таймер, пользователь что-то щелкает и т. Д.).
Иногда, однако, вам придется избавляться от этих временных объектов раньше, чем позже. Например, вам нужно обработать огромный многомегабайтный файл или десятки тысяч строк из базы данных. Когда это происходит, вам нужно поместить NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
в хорошо выбранную точку, а затем [pool release];
внизу. Это почти всегда происходит при некоторой «пакетной обработке цикла», поэтому обычно это начало и конец некоторого критического цикла. Опять же, это должно быть основано на доказательствах, а не на догадках. ObjectAlloc от Instrument.app - это то, что вы используете для поиска этих проблем.
Основная причина, по которой я предпочитаю autorelease
, а не release
, заключается в том, что на 1015 * намного проще писать программы без утечек. Короче говоря, если вы решите пойти по маршруту release
, вам необходимо гарантировать , что release
в конечном итоге будет отправлено на obj
, под all обстоятельства. Хотя это может показаться простым, на практике это удивительно сложно. Возьмите ваш пример, например:
// array is an instance of NSMutableArray
MyClass *obj = [[MyClass alloc] init];
[array addObject:obj];
// Assume a few more lines of work....
[obj release];
Теперь представьте, что по какой-то причине что-то где-то слегка нарушает ваше предположение, что array
является изменчивым, возможно, в результате использования какого-либо метода для обработки результатов, и возвращенный массив, содержащий обработанные результаты, был создан как NSArray
. Когда вы отправляете addObject:
на этот неизменный NSArray
, возникает исключение, и вы никогда не отправите obj
его release
сообщение. Или, может быть, что-то идет не так, когда между obj
было alloc
d и требуется вызов release
, как будто вы проверили какое-то условие и return()
сразу по ошибке, потому что ваше мнение о том, что это Позвоните release
позже обязательно .
Вы только что слили объект. И, вероятно, подписался на несколько дней, пытаясь выяснить, где и почему это ваша утечка. Исходя из опыта, вы потратите много часов на просмотр этого кода выше, убедившись, что он не может быть источником утечки, потому что вы очень четко отправили obj
a release
. Затем, через несколько дней, вы почувствуете то, что можно назвать только религиозным прозрением, поскольку вы понимаете причину проблемы.
Рассмотрим случай autorelease
:
// array is an instance of NSMutableArray
MyClass *obj = [[[MyClass alloc] init] autorelease];
[array addObject:obj];
// Assume a few more lines of work....
Теперь, больше не имеет значения, что происходит, потому что практически невозможно протечь obj
случайно, даже в чрезвычайно необычных или исключительных случаях.