Почему релиз часто вызывается вскоре после использования локальной переменной вместо автоматического выпуска?

Я часто вижу что-то вроде следующего:

UIBarButtonItem *anotherButton = [[UIBarButtonItem alloc] initWithTitle:@"Show" style:UIBarButtonItemStylePlain target:self action:@selector(refreshPropertyList:)];          
  self.navigationItem.rightBarButtonItem = anotherButton;
  [anotherButton release];

в частности, когда используется локальная переменная, в данном случае «anotherButton», а затем освобождается. Является ли это точно таким же, как его автоматическое освобождение, когда оно выделено, а затем проверка того, что оно используется до завершения метода? то есть:

UIBarButtonItem *anotherButton = [[[UIBarButtonItem alloc] initWithTitle:@"Show" style:UIBarButtonItemStylePlain target:self action:@selector(refreshPropertyList:)] autorelease];          
  self.navigationItem.rightBarButtonItem = anotherButton;

Я спрашиваю, потому что я вижу, что это делается первым способом огромное количество времени, но мне кажется менее подверженным ошибкам (для меня) просто автоматически выпускать его напрямую. Является ли это просто вопросом личного стиля или существуют различия между этими двумя подходами, за исключением того, что один методично выпускает объект после того, как с ним сделано все, а другой заботится о том, чтобы объявить об освобождении объекта в самом начале, чтобы никто случайно не забудьте, оба имеют достоинства.


person Joey    schedule 03.05.2011    source источник


Ответы (4)


Из раздела Разумное выделение памяти в Настройка производительности и скорости отклика Таблица 7-2. Советы по выделению памяти:

Совет

Сократите использование автоматически выпускаемых объектов.

Действия, которые необходимо предпринять

Объекты, выпущенные с помощью метода автоматического освобождения, остаются в памяти до тех пор, пока вы явно не очистите текущий пул автоматического освобождения или до следующего раза в цикле обработки событий. По возможности избегайте использования метода автоматического освобождения, если вместо этого можно использовать метод освобождения для немедленного освобождения памяти, занятой объектом. Если вам необходимо создать умеренное количество автоматически освобождаемых объектов, создайте локальный пул автоматического освобождения и периодически очищайте его, чтобы освободить память для этих объектов до следующего цикла событий.

person albertamg    schedule 03.05.2011
comment
В этом случае, однако, маловероятно, что немедленное освобождение объекта освободит память, поскольку она, вероятно, будет сохранена элементом навигации. Учитывая это, это действительно сводится к вопросу стиля. (Да, я понимаю, что не следует полагаться на то, что другие объекты могут или не могут делать с куском памяти. кнопку на несколько микросекунд может иметь значение.) - person Caleb; 03.05.2011
comment
Спасибо, это деталь, которую я упустил при RTFM. Тем не менее, беспокойство о размере вашего пула автоматического выпуска до следующего цикла событий кажется анальным в случае подавляющего большинства приложений iOS. Если вы запускаете какой-то алгоритм с сотнями или тысячами итераций и помещаете объекты в пул автоматического освобождения, я вижу, что это очень важно, но когда мы говорим о размещении 5-10 объектов в пуле при распределении новый вид, прежде чем пользователь выберет свое следующее действие, как часто это будет иметь значение? - person Thomson Comer; 04.05.2011
comment
Ключевая фраза в процитированном отрывке — умеренные цифры. - person Caleb; 04.05.2011

Когда вы автоматически освобождаете что-то, вы добавляете это в группу объектов, которые будут освобождены в какой-то момент в будущем. Это означает, что эти объекты все еще существуют. Поскольку iOS предоставляет ограниченный объем памяти, рекомендуется по возможности использовать выпуск вместо автоматического выпуска. Вы не хотите, чтобы ваша программа аварийно завершала работу из-за нехватки памяти, потому что у вас есть много автоматически освобождаемых объектов.

person ughoavgfhw    schedule 03.05.2011

Отличный вопрос. Выполняя автоматическое освобождение, вы задерживаете автоматическое освобождение объектов. Это все нормально, красиво и ожидаемо, когда вам нужно что-то вернуть из метода, но хранение этого объекта в памяти дольше, чем необходимо, может повлиять на ваше приложение.

Освобождая его, когда вы закончите, вы освобождаете ресурс в этот момент, и память может использоваться другим объектом во время выполнения. В Cocos2D является стандартной практикой автоматическое освобождение почти всего, и кажется, что все работает нормально, но это все еще раздражает меня, и я бы не стал этого делать в обычной практике.

person Wayne Hartman    schedule 03.05.2011

Они выполняют одно и то же. Некоторые люди считают, что вам следует избегать использования автовыпуска, когда это возможно, поэтому настоятельно рекомендую выпускать его как можно скорее. Это обсуждалось здесь буквально вчера.

В коде, который вы цитируете, разница между ними действительно минимальна. Маловероятно, что anotherButton будет освобожден даже после его освобождения, потому что назначение self.navigationItem.rightBarButtonItem, вероятно, приведет к сохранению anotherButton.

Лучший аргумент в пользу вызова релиза как можно скорее, IMO и в этой ситуации, заключается в том, что, выпуская anotherButton, вы явно документируете тот факт, что вы закончили его использовать. Кроме того, статический анализатор будет звонить вам, если вы используете anotherButton после релиза. Эти два факта могут помочь вам избежать ошибок и сделать ваш код более понятным.

Аргумент в пользу автоматического освобождения в такой ситуации заключается в том, что его может быть немного легче читать. Я думаю, что есть причина, по которой Apple предоставляет нам все эти удобные методы, такие как +stringWithFormat: — они позволяют создавать и использовать нужную строку одним методом, а не тремя.

person Caleb    schedule 03.05.2011