Основы: Каковы официальные причины отказа от использования retainCount?
Управление автоматическим выпуском является наиболее очевидным - вы не можете быть уверены, сколько ссылок представленоretainCount
находятся в локальном или внешнем (во вторичном потоке или в локальном пуле другого потока) пуле автоматического выпуска.
Кроме того, у некоторых людей возникают проблемы с утечками, а также с подсчетом ссылок более высокого уровня и тем, какАвто-релизы работают на фундаментальных уровнях.Они напишут программу без (большого) отношения к правильному подсчету ссылок или без правильного подсчета ссылок.Это делает их программу очень трудной для отладки, тестирования и улучшения - это также очень трудоемкое исправление.
Причина, препятствующая ее использованию (на уровне клиента), двояка:
1) Значение может варьироваться по многим причинам. Одной лишь многопоточности является достаточной причиной, чтобы никогда ей не доверять.
2) Вам все еще нужно реализовать правильный подсчет ссылок.retainCount
никогда не спасет вас от несбалансированного подсчета ссылок.
Есть ли вообще какая-либо ситуация, когда она может быть полезна?
Вы может фактически использовать его осмысленно, если вы написали свои собственные распределители или схему подсчета ссылок, или если ваш объект жил в одном потоке, и у вас был доступ к любым и всем пулам автоматического выпускаон может существовать в. Это также означает, что вы не будете делиться им с какими-либо внешними API.Самый простой способ смоделировать это - создать программу с одним потоком, нулевым пулом автоматического выпуска и выполнить подсчет ссылок «нормальным» способом.Маловероятно, что вам когда-нибудь понадобится решить эту проблему / написать эту программу по каким-либо иным причинам, кроме «академических».
В качестве средства отладки: вы могли бы использовать его, чтобы убедиться, чтосохранить количество не является необычно высоким.Если вы выберете такой подход, помните о различиях в реализации (некоторые процитированы в этом посте) и не полагайтесь на них.Даже не передавайте тесты в свой репозиторий SCM.
Это может быть полезно для диагностики в крайне редких случаях.Его можно использовать для обнаружения:
Чрезмерное удержание: распределение с положительным дисбалансом в счетчике удержания не будет отображаться как утечка, если распределение доступно вашей программе.
Объект, на который ссылаются многие другие объекты. Одной из иллюстраций этой проблемы является (изменяемый) общий ресурс или коллекция, которая работает в многопоточном контексте - частый доступ или изменения к этому ресурсу / коллекцииможет привести к значительному узкому месту в выполнении вашей программы.
Уровни автоматического освобождения: автоматическое освобождение, пулы автоматического освобождения и циклы сохранения / автоматического освобождения - все это обходится дорого.Если вам необходимо минимизировать или уменьшить использование и / или увеличение объема памяти, вы можете использовать этот подход для выявления чрезмерных случаев.
Из комментария с Bavarious (ниже): высокое значение также может указыватьнедействительное распределение (экземпляр dealloc'd).Это полностью деталь реализации, и опять же, ее нельзя использовать в производственном коде.Сообщение об этом распределении может привести к ошибке при включении зомби.
Что нужно сделать вместо этого?
Если вы не несете ответственности за возврат памяти на self
(то есть вы не написали распределитель), оставьте его в покое - это бесполезно.
Вы должны научиться правильному подсчету ссылок.
Для лучшего понимания использования выпуска и автоматического выпускаустановите некоторые контрольные точки и поймите, как они используются, в каких случаях и т. д. Вам все равно придется научиться правильно использовать подсчет ссылок, но это может помочь вам понять, почему это бесполезно.
Еще проще: используйте инструменты для отслеживания выделения и подсчета ссылок, затем анализируйте подсчет ссылок и стеки вызовов для нескольких объектов в активной программе.
Историческая справка: почему Apple предоставляет этот метод в протоколе NSObject, если он не предназначен для использования? Код Apple полагается на retainCount для какой-то цели? Если так, то почему он не спрятан где-то?
Мы можем предположить, что он публичный по двум основным причинам:
1) Правильный подсчет ссылок в управляемых средах. Распределители могут использовать retainCount
- действительно. Это очень простая концепция. Когда вызывается -[NSObject release]
, может быть вызван счетчик ссылок (если он не переопределен), и объект может быть освобожден, если retainCount
равно 0 (после вызова dealloc). Это все хорошо на уровне распределителя. Распределители и зоны (в основном) абстрагированы, так что ... это делает результат бессмысленным для обычных клиентов. См. Комментарий к bbum (ниже), чтобы узнать, почему retainCount
не может быть равно 0 на уровне клиента, освобождение объекта, последовательности освобождения и т. Д.
2) Сделать его доступным для субклассеров, которым нужно пользовательское поведение, а также потому, что другие методы подсчета ссылок являются общедоступными. В некоторых случаях это может быть удобно, но обычно используется по неправильным причинам (например, бессмертные одиночки). Если вам нужна собственная схема подсчета ссылок, возможно, стоит переопределить эту семью.
Для более глубокого понимания: каковы причины того, что объект может иметь другое количество сохранений, чем предполагалось бы из кода пользователя? Можете ли вы привести примеры *** стандартных процедур, которые может использовать базовый код, которые вызывают такую разницу? Известны ли случаи, когда счет сохранения всегда отличается от ожидаемого новым пользователем?
Опять пользовательские схемы подсчета ссылок и бессмертных объектов. NSCFString
литералы попадают в последнюю категорию:
NSLog(@"%qu", [@"MyString" retainCount]);
// Logs: 1152921504606846975
Что еще, по вашему мнению, стоит упомянуть о retainCount?
Это бесполезно в качестве средства отладки. Научитесь использовать анализ утечек и зомби, и используйте их часто - даже после у вас есть ручка подсчета ссылок.
Обновление: bbum недавно опубликовал статью под названием retainCount бесполезен . Статья содержит подробное обсуждение того, почему -retainCount
бесполезен в подавляющем большинстве случаев.