dealloc у Свіфті


145

Я хотів би здійснити чистку в кінці життя контролера перегляду, а саме видалити NSNotificationCenterсповіщення. Реалізація deallocрезультатів у помилці компілятора Swift:

Cannot override 'dealloc' which has been marked unavailable

Який найкращий спосіб здійснити чистку в кінці життя об'єкта в Свіфті?

Відповіді:


333
deinit {
    // perform the deinitialization
}

З документації Swift :

Дезініціалізатор викликається безпосередньо перед розміщенням екземпляра класу. Ви пишете деініціалізатори з ключовим словом deinit, подібно до того, як пишеться intializer за допомогою ключового слова init. Дезініціалізатори доступні лише для типів класу.

Зазвичай вам не потрібно проводити очищення вручну, коли ваші екземпляри розміщені. Однак, працюючи з власними ресурсами, можливо, вам доведеться самостійно виконати додаткову очистку. Наприклад, якщо ви створюєте спеціальний клас, щоб відкрити файл і записати до нього деякі дані, можливо, вам доведеться закрити файл, перш ніж екземпляр класу буде розміщений.


45
deinit {
    // perform the deinitialization
}

є правильною відповіддю для Свіфта "угода".

Однак добре вказувати нове в iOS 9, що NSNotificationCenter більше не потрібно прибирати!

https://developer.apple.com/library/content/releasenotes/Foundation/RN-FoundationOlderNotes/index.html#X10_11Замітки

NSNotificationCenter

В OS X 10.11 та iOS 9.0 NSNotificationCenter та NSDistributedNotificationCenter більше не надсилатимуть повідомлення зареєстрованим спостерігачам, які можуть бути розміщені. Якщо спостерігач може зберігатись як нульове слабке посилання, то базовий сховище зберігатиме спостерігача як нульове слабке посилання, або, якщо об'єкт не може бути збережений слабко (тобто він має спеціальний механізм збереження / звільнення, який би перешкоджав виконанню від можливості слабко зберігати об’єкт) він буде зберігати об’єкт як слабку нульову посилання. Це означає, що від спостерігачів не потрібно реєструватися у своєму методі розселення. Наступне повідомлення, яке буде перенаправлено до цього спостерігача, виявить нульову посилання та автоматично скасує реєстратора. Якщо об’єкт може бути слабо посилається, сповіщення більше не надсилатиметься спостерігачеві під час угоди. попередня поведінка прийому сповіщень під час трансакцій все ще присутня у випадку слабких нульових референтних спостерігачів. Блокувати спостерігачів за допомогою методу - [NSNotificationCenter addObserverForName: object: queue: usingBlock] все ще потрібно скасувати реєстрацію, коли він більше не використовується, оскільки система все ще має чітке посилання на цих спостерігачів. Передчасне видалення спостерігачів (з посиланням на слабку або нульову) досі підтримується. CFNotificationCenterAddObserver не відповідає цій поведінці, оскільки спостерігач не може бути об'єктом. Блокувати спостерігачів за допомогою методу - [NSNotificationCenter addObserverForName: object: queue: usingBlock] все ще потрібно скасувати реєстрацію, коли він більше не використовується, оскільки система все ще має чітке посилання на цих спостерігачів. Передчасне видалення спостерігачів (з посиланням на слабку або нульову) досі підтримується. CFNotificationCenterAddObserver не відповідає цій поведінці, оскільки спостерігач не може бути об'єктом. Блокувати спостерігачів за допомогою - [NSNotificationCenter addObserverForName: object: queue: usingBlock] метод все ще потрібно скасувати реєстрацію, коли він більше не використовується, оскільки система все ще має чітке посилання на цих спостерігачів. Передчасне видалення спостерігачів (з посиланням на слабку або нульову) досі підтримується. CFNotificationCenterAddObserver не відповідає цій поведінці, оскільки спостерігач не може бути об'єктом.

але зверніть увагу на пункти нижче про чіткі посилання, тож вам, можливо, доведеться турбуватися про очищення ...?


3
Якщо блок сповіщень не має чітких посилань, слід усунути спостерігача.
TigerCoding

+1 за те, що не потрібно прибирати спостерігачів. Важливо знати! Я роблю всі захоплення посиланнями слабкими, тому ніколи не маю цього мати справу.
n13,

2
Блоки сповіщень завжди здаються сильно посилаються згідно з документацією. Отже: Якщо ви використовуєте блоки для обробки сповіщень, вам доведеться скасувати реєстрацію на них всередині deinit.
marsbear

22

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Deinitialization.html

Swift автоматично розміщує ваші випадки, коли вони більше не потрібні, щоб звільнити ресурси. Swift обробляє управління пам’яттю екземплярів за допомогою автоматичного підрахунку довідок (ARC), як описано в автоматичному підрахунку довідок. Зазвичай вам не потрібно проводити очищення вручну, коли ваші екземпляри розміщені. Однак, працюючи з власними ресурсами, можливо, вам доведеться самостійно виконати додаткову очистку. Наприклад, якщо ви створюєте спеціальний клас, щоб відкрити файл і записати до нього деякі дані, можливо, вам доведеться закрити файл, перш ніж екземпляр класу буде розміщений.

Визначення класів можуть мати не більше одного дезініціалізатора на клас. Дезініціалізатор не приймає жодних параметрів і записується без дужок:

deinit {
    // perform the deinitialization
}

2

видалення спостерігача потрібно перед розселенням, інакше трапиться аварія. Це можна зробити за допомогою

deinit {
    // perform the deinitialization
    print("deinit")

    removeObserver(self, forKeyPath: kSelectedViewControllerKey, context: nil)
    removeObserver(self, forKeyPath: kSelectedIndexKey, context: nil)

}

-2

Будьте обережні, викликаючи метод в іншому класі з deinit, він, ймовірно, закінчиться крахом


1
Це не повинно бути обов'язково. З реф. Документи : Оскільки екземпляр не розміщений до моменту виклику його деінціалізатора, деінціалізатор може отримати доступ до всіх властивостей екземпляра, на який він викликається, і може змінити свою поведінку на основі цих властивостей (наприклад, пошук імені файлу, для якого потрібно бути закритим).
superjos
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.