Когда использовать -retainCount? - PullRequest
107 голосов
/ 09 января 2011

Я хотел бы знать, в какой ситуации вы использовали -retainCount до сих пор, и в конечном итоге проблемы, которые могут возникнуть при его использовании.

Спасибо.

Ответы [ 11 ]

240 голосов
/ 09 января 2011

Вы никогда не должны использовать -retainCount, потому что это никогда не говорит вам ничего полезного. Реализация платформ Foundation и AppKit / UIKit непрозрачна; вы не знаете, что хранится, почему оно сохраняется, кто его хранит, когда оно сохраняется и т. д.

Например:

  • Вы могли бы подумать, что [NSNumber numberWithInt:1] будет иметь retainCount 1. Это не так. Это 2.
  • Вы могли бы подумать, что @"Foo" будет иметь retainCount 1. Это не так. Это 1152921504606846975.
  • Вы могли бы подумать, что [NSString stringWithString:@"Foo"] будет иметь retainCount 1. Это не так. Опять же, это 1152921504606846975.

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

Если вы пытаетесь выяснить, почему объект не освобождается, используйте инструмент «Утечки» в инструментах. Если вы пытаетесь выяснить, почему объект был освобожден слишком рано, используйте инструмент Зомби в Инструментах.

Но не используйте -retainCount. Это действительно бесполезный метод.

редактировать

Пожалуйста, перейдите на http://bugreport.apple.com и попросите, чтобы -retainCount устарело. Чем больше людей просят об этом, тем лучше.

edit # 2

В качестве обновления [NSNumber numberWithInt:1] теперь имеет retainCount 9223372036854775807. Если ваш код ожидал, что он будет равен 2, ваш код теперь не работает.

51 голосов
/ 09 января 2011

НИКОГДА!

Серьезно. Только не делай этого.

Просто следуйте Руководству по управлению памятью и выпускайте только то, что вы alloc, new или copy (или все, что вы называли retain изначально).

@ bbum сказал, что лучше всего здесь, на SO , и еще более подробно на его блоге .

14 голосов
/ 09 января 2011

Автоматически освобожденные объекты - это один из случаев, когда проверка -retainCount неинформативна и может вводить в заблуждение. Подсчет сохранения ничего не говорит вам о том, сколько раз -autorelease вызывался для объекта и, следовательно, сколько раз он будет освобожден, когда текущий пул авто-выпуска истощается.

10 голосов
/ 10 мая 2011

I do находят retainCounts очень полезными при проверке с использованием инструментов.

Используя инструмент «распределения», убедитесь, что «Счетчик ссылок на записи» включен, и вы можете перейти к любому объекту и просмотреть его историю retainCount.

Сопрягая ресурсы и выпуски, вы можете получить хорошее представление о происходящем и часто решать те сложные случаи, когда что-то не выпускается.

Это никогда не подводило меня, включая поиск ошибок в ранних бета-версиях iOS.

5 голосов
/ 09 января 2011

Взгляните на документацию Apple по NSObject, она в значительной степени охватывает ваш вопрос: NSObject retainCount

Короче говоря, retainCount, вероятно, бесполезен для вас, если вы не внедрили свой собственныйсистема подсчета ссылок (и я почти гарантирую, что у вас ее не будет).

По собственным словам Apple, retainCount "обычно не имеет значения при отладке проблем управления памятью".

3 голосов
/ 29 ноября 2015

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

Стремясь подчеркнуть свою точку зрения, вы серьезно преувеличивали непостижимый характер ценности. Это правда, что это не всегда счетчик ссылок. Есть некоторые специальные значения, которые используются для флагов, например, чтобы указать, что объект никогда не должен быть освобожден. Число вроде 1152921504606846975 выглядит очень загадочно, пока вы не напишите его в шестнадцатеричном виде и не получите 0xfffffffffffffff. И 9223372036854775807 - это 0x7fffffffffffffff в шестнадцатеричном формате. И на самом деле неудивительно, что кто-то выбрал бы использование таких значений в качестве флагов, учитывая, что для получения retainCount потребуется больше 3000 лет, чем для большего числа, при условии, что вы увеличили retainCount 100 000 000 раз в секунду.

3 голосов
/ 09 января 2011

Вам не следует беспокоиться об утечке памяти, пока ваше приложение не заработает и не сделает что-то полезное.

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

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

Попробуйте написать правильный код, например, если вы создаете объект с использованием alloc и тому подобного, убедитесь, что вы правильно его освободили.

3 голосов
/ 09 января 2011

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

0 голосов
/ 04 июня 2018

Примеры, использованные в посте Дэйва, - это NSNumber и NSStrings ... так что, если вы используете некоторые другие классы, такие как UIViews, я уверен, что вы получите правильный ответ (Счетчик сохранения зависит от реализации, и это предсказуемы).

0 голосов
/ 04 мая 2013

Никогда не используйте -retainCount в вашем коде.Однако, если вы используете, вы никогда не увидите, что он возвращает ноль.Подумай почему.: -)

...