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

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

@property (nonatomic,weak) id delegate;

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

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

Ответы [ 4 ]

91 голосов
/ 09 декабря 2011

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

26 голосов
/ 10 декабря 2011

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

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

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

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

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

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

18 голосов
/ 09 декабря 2011

Это чтобы избежать сохранения циклов.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.

3 голосов
/ 29 августа 2014

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...