Следует ли переопределить deinit для удаления наблюдателей в Swift?

Товарищи по команде написали код, например,

deinit {
    NotificationCenter.default.removeObserver(self)
}

Я прокомментировал, чтобы удалить это, так как наблюдатели уже позаботились о структуре. Товарищи по команде хотят сохранить этот код, если нет побочных эффектов. Теперь, даже если мы сохраним этот код выше, есть ли какой-нибудь побочный эффект?

Должен ли я также вызывать super.deinit() внутри deinit?


person Sazzad Hissain Khan    schedule 24.02.2020    source источник
comment
Вы спрашиваете, следует ли переопределить deinit вообще (как указано в заголовке) или его следует переопределить для удаления наблюдателя?   -  person Martin R    schedule 24.02.2020
comment
@MartinR изменил название   -  person Sazzad Hissain Khan    schedule 24.02.2020
comment
Сравните stackoverflow.com/q/25069480/1187415 и stackoverflow.com/q/53394779/1187415.   -  person Martin R    schedule 24.02.2020
comment
@MartinR Ответ на 1-е сообщение датирован 6 годами назад (Я слышал, что в ARC есть некоторые изменения), а ответ на 2-е сообщение не указал на проблему.   -  person Sazzad Hissain Khan    schedule 24.02.2020


Ответы (2)


Начиная с iOS 9 вам не нужно самостоятельно удалять наблюдателей, если вы не используете наблюдателей на основе блоков. Система сделает это за вас, так как она использует слабо обнуляемые ссылки для наблюдателей, где это возможно.

Если наблюдатель может быть сохранен как обнуляемая слабая ссылка, базовое хранилище будет хранить наблюдателя как обнуляющую слабую ссылку, в качестве альтернативы, если объект не может быть сохранен слабо (т. из-за возможности слабо хранить объект) он будет хранить объект как неслабую обнуляющую ссылку. Это означает, что наблюдатели не обязаны отменять регистрацию в своем методе освобождения.

Наблюдатели на основе блоков с помощью метода -[NSNotificationCenter addObserverForName: object: queue: usingBlock] по-прежнему необходимо отменить регистрацию, если они больше не используются, поскольку система по-прежнему содержит строгую ссылку на этих наблюдателей.

Документы Apple

а для super.deinit() яблоко говорит

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

документы по Swift

person Jawad Ali    schedule 24.02.2020

Да, это действительно для переопределения

deinit()

Как указано в комментариях. Супер не нужно вызывать. Я подтвердил это в документах Apple.

Явная очистка - хорошая идея. Особенно, когда речь идет о потоках, уведомлениях и таймерах.

person Woodstock    schedule 24.02.2020
comment
super.deinit() вызывается неявно в Swift, вы не можете вызывать его явно: «ошибка: доступ к деинициализаторам недоступен». - person Martin R; 24.02.2020