Подтвердить что ты не робот

Слабый или сильный для IBOutlet и других

Я переключил свой проект на ARC, и я не понимаю, должен ли я использовать strong или weak для IBOutlets. Xcode делает это: в построителе интерфейсов, например, для создания UILabel, и я подключаю его с помощником редактора к моему ViewController, он создает это:

@property (nonatomic, strong) UILabel *aLabel;

Он использует strong, вместо этого я прочитал учебник на веб-сайте RayWenderlich, который говорит следующее:

Но для этих двух конкретных свойств у меня есть другие планы. Вместо strong, мы объявим их как weak.

@property (nonatomic, weak) IBOutlet UITableView *tableView;
@property (nonatomic, weak) IBOutlet UISearchBar *searchBar;

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

В настоящее время наш viewDidUnload выглядит так:

- (void)viewDidUnload
{
    [super viewDidUnload];
    self.tableView = nil;
    self.searchBar = nil;
    soundEffect = nil;
}

Теперь вы можете упростить его:

- (void)viewDidUnload
{
    [super viewDidUnload];
    soundEffect = nil;
}

Поэтому используйте weak вместо strong и удалите набор в nil в videDidUnload, вместо Xcode используйте strong и используйте self... = nil в viewDidUnload.

Мой вопрос: когда мне нужно использовать strong, а когда weak? Я хочу также использовать для цели развертывания iOS 4, поэтому, когда мне нужно использовать unsafe_unretain? Любой может помочь мне хорошо объяснить небольшой учебник, когда используйте strong, weak и unsafe_unretain с ARC?

4b9b3361

Ответ 1

Эмпирическое правило

Когда родитель имеет ссылку на дочерний объект, вы должны использовать ссылку strong. Когда у ребенка есть ссылка на его родительский объект, вы должны использовать ссылку weak или unsafe_unretained (если первая не доступна). Типичный сценарий - это когда вы имеете дело с делегатами. Например, UITableViewDelegate не сохраняет класс контроллера, который содержит представление таблицы.

enter image description here

Вот простая схема, чтобы представить основные понятия.

Предположим, что первые 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?

Какие утечки делает автоматический подсчет ссылок в Objective-C не предотвращать или сводить к минимуму?

используя ARC, назначение квалификатора lifetime и unsafe_unretained

strong/weak/retain/unsafe_unretained/assign

Надеюсь, что это поможет.

Обновление

Согласно комментарию shaunlim, начиная с iOS 6 viewDidUnload метод устарел. Здесь я действительно предлагаю увидеть ответ Роба: iOS 6 - viewDidUnload перейти на didReceiveMemoryWarning?.

Ответ 2

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

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

Если вы зарегистрированный разработчик, я настоятельно рекомендую вам посмотреть видео с WWDC11 и WWDC12. Другим хорошим ресурсом является подкаст разработки iOS от Stanford.