Меня всегда смущало, должны ли делегаты быть слабыми или нет. Недавно я узнал больше о делегатах и о том, когда использовать слабые ссылки, поэтому позвольте мне добавить некоторые дополнительные замечания здесь для будущих зрителей.
Цель использования weak
ключевого слова - избежать циклов сильных ссылок (сохранить циклы). Сильные ссылочные циклы происходят, когда два экземпляра класса имеют сильные ссылки друг на друга. Их счетчик ссылок никогда не обнуляется, поэтому их никогда не освобождают.
Вам нужно использовать только weak
если делегат является классом. Структуры и перечисления Swift являются типами значений (их значения копируются при создании нового экземпляра), а не ссылочными типами, поэтому они не создают сильных ссылочных циклов.
weak
ссылки всегда являются необязательными (в противном случае вы бы их использовали unowned
) и всегда используете var
(не let
), так что необязательный может быть установлен, nil
когда он освобожден.
Естественно, родительский класс должен иметь строгую ссылку на свои дочерние классы и поэтому не должен использовать weak
ключевое слово. Когда ребенок хочет ссылку на своего родителя, он должен сделать его слабой ссылкой, используя weak
ключевое слово.
weak
должен использоваться, когда вы хотите ссылку на класс, который вам не принадлежит, а не только на ребенка, ссылающегося на его родителя. Когда два неиерархических класса должны ссылаться друг на друга, выберите один, чтобы быть слабым. Выбор зависит от ситуации. Смотрите ответы на этот вопрос для получения дополнительной информации по этому вопросу.
Как правило, делегаты должны быть помечены так,weak
потому что большинство делегатов ссылаются на классы, которыми они не владеют. Это определенно верно, когда ребенок использует делегата для общения с родителем. Использование слабой ссылки для делегата - это то, что рекомендует документация . (Но посмотрите и это тоже.)
Протоколы могут использоваться как для ссылочных типов (классов), так и для типов значений (структуры, перечисления). Таким образом, в вероятном случае, когда вам нужно сделать делегата слабым, вы должны сделать его протоколом только для объекта. Способ сделать это - добавить AnyObject
в список наследования протокола. (В прошлом вы делали это с помощью class
ключевого слова, но AnyObject
сейчас это предпочтение .)
protocol MyClassDelegate: AnyObject {
// ...
}
class SomeClass {
weak var delegate: MyClassDelegate?
}
Чтение следующих статей помогло мне понять это намного лучше. Они также обсуждают связанные вопросы, такие как unowned
ключевое слово и циклы сильных ссылок, которые происходят с замыканиями.