Ответ 1
Эмпирическое правило
Когда родитель имеет ссылку на дочерний объект, вы должны использовать ссылку strong
. Когда у ребенка есть ссылка на его родительский объект, вы должны использовать ссылку weak
или unsafe_unretained
(если первая не доступна). Типичный сценарий - это когда вы имеете дело с делегатами. Например, UITableViewDelegate
не сохраняет класс контроллера, который содержит представление таблицы.
Вот простая схема, чтобы представить основные понятия.
Предположим, что первые A, B и C являются ссылками strong
. В частности, C имеет strong
ref для своего родителя. Когда obj1 освобождается (где-то), ссылка A больше не существует, но у вас есть утечка, так как между объектами obj1 и obj2 существует цикл. Говоря в терминах подсчета удержания (только для объяснения целей), obj1 имеет счетчик удержания 2 (obj2 имеет ссылку strong
), а obj2 имеет показатель сохранения 1. Если obj1, его счетчик хранения теперь равен 1, и его метод dealloc
не вызывается. obj1 и obj2 все еще остаются в памяти, но никто не ссылается на них: Leak.
В противоположность, если только A и B являются strong
refs, а C - как weak
, все в порядке. У вас нет утечек. Фактически, когда obj1 освобождается, он также освобождает obj2. Говоря в терминах счетчиков удержаний, obj1 имеет счетчик удержания 1, obj2 имеет показатель сохранения 1. Если obj1 освобождается, его счетчик сохранения теперь равен 0 и его метод dealloc
вызывается. obj1 и obj2 удаляются из памяти.
Простое предложение: начните думать в терминах графа объектов при работе с ARC.
О вашем первом вопросе, оба решения действительны, когда вы имеете дело с XIB. Обычно weak
ссылки используются, когда вы имеете дело с циклами памяти.
Что касается файлов XIB, если вы используете strong
, вам нужно установить nil
в viewDidUnload
, так как если вы этого не сделаете, в условиях низкой памяти вы можете вызвать неожиданные утечки. Вы не выпускаете их в dealloc
, потому что ARC сделает это за вас.
weak
вместо этого не нуждается в этом лечении, поскольку, когда целевой объект уничтожается, эти значения устанавливаются как nil
автоматически. Нет никаких оборванных указателей.
Если вас интересует, я действительно предлагаю вам прочитать friday-qa-2012-04-13-nib-memory-management Майк Эш.
О вашем втором вопросе, если вам нужно поддерживать iOS 4 вместо weak
, вы должны использовать unsafe_unretained
.
Внутри SO есть много вопросов/ответов. Здесь основные:
Как заменить слабые ссылки при использовании ARC и таргетинга на iOS 4.0?
используя ARC, назначение квалификатора lifetime и unsafe_unretained
strong/weak/retain/unsafe_unretained/assign
Надеюсь, что это поможет.
Обновление
Согласно комментарию shaunlim, начиная с iOS 6 viewDidUnload
метод устарел. Здесь я действительно предлагаю увидеть ответ Роба: iOS 6 - viewDidUnload перейти на didReceiveMemoryWarning?.