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

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

Я не могу понять, почему правильно определить делегат со слабым указателем:

@property (nonatomic,weak) id delegate;

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

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

Я искал другие вопросы о переполнении стека, но я не могу найти что-то, что может помочь мне полностью понять эту ситуацию.

4b9b3361

Ответ 1

Причина, по которой объекты слабо удерживают своих делегатов, заключается в том, чтобы избежать сохранения циклов. Представьте себе следующий сценарий: object a создает b и сохраняет его, затем устанавливает себя как делегат b. a освобождается его владельцем, оставляя цикл сохранения, содержащий a и b. Это на самом деле очень распространенный сценарий. Рассмотрим контроллер представления, который владеет представлением и выступает в качестве делегата представления. В этом случае представление не должно удерживать контроллер как материю надлежащей архитектуры MVC и предотвращать циклы сохранения.

Ответ 2

Несмотря на то, что сохраняющиеся циклы являются действительной проблемой, аргументация относительно слабой ссылки больше связана с перспективой Apple о том, как использовать шаблон делегирования с uikit и другими элементами из поля, который здесь объясняется:

http://developer.apple.com/library/IOs/documentation/General/Conceptual/DevPedia-CocoaCore/Delegation.html

В частности: "Главное значение делегирования заключается в том, что он позволяет легко настраивать поведение нескольких объектов в одном центральном объекте".

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

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

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

Ответ 3

Это необходимо, чтобы избежать циклов сохранения. Apple предлагает информативное руководство по расширенному управлению памятью, объясняя ситуацию и как лучше всего с ней справиться. В ARC они теперь известны как сильные ссылочные циклы, которые объясняются в Переход к заметкам о выпуске ARC.

Раньше вы определяли бы свойство для такого делегата,

@property (nonatomic, assign) id delegate;

Но в ARC вы можете определить его таким образом,

@property (nonatomic, unsafe_unretained) id delegate;

Или, например, если у вас есть протокол с именем <MyObjectDelegate>, вы также можете определить делегат,

@property (nonatomic, weak) id <MyObjectDelegate> delegate;

Другими словами, в ARC, если у вас есть протокол, вы можете объявить делегат weak. В противном случае unsafe_unretained.

Ответ 4

Как обычная практика, если у нас есть два объекта, содержащих ссылки друг с другом, мы делаем "дочерний" объект в отношении "родительские дети" слабым эталоном.
Для делегирующих паттернов в iOS делегированный объект является родительским, потому что нет необходимости, чтобы вызывающий делегат существовал без делегированного объекта. Например, у вас есть объект предложения с объектом-делегатом для метода предложениеShouldEnd. Ваш объект абзаца является делегированным объектом для объекта предложения. Очевидно, что объект абзаца на самом деле является родителем, а в объекте предложения вы должны держать своего делегата в качестве слабой ссылки.
К вашему моменту вы назначаете делегата себе, ваше понимание ошибочно. Мы никогда не должны присваивать себе делегат. Почему вы сами покупаете свой билет, если считаете необходимым нанять агента, чтобы купить билет для вас? Вы говорите два совершенно разных понятия. Когда вы определяете объект delegate как свойство, он использовал слабую ссылку в объекте, в котором он определен (позволяет сказать, что A, то есть объект-делегат является свойством A). Делегат назначается, когда вы начинаете A (скажем, в B), тогда, скорее всего, вы бы присвоили A.delegate себе, что является актурально B. Вы видите здесь отношения родитель-ребенок? Вы выделяете память для A в B. Вы удерживаете A в B. A не существует без B. Вы не назначаете делегата A!!!!