Dealloc в Свифт

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

Cannot override 'dealloc' which has been marked unavailable

Каков предпочтительный способ выполнить некоторую очистку в конце жизни объекта в Swift?

Ответ 1

deinit {
    // perform the deinitialization
}

Из Swift Documentation:

Деинициализатор вызывается непосредственно перед экземпляром класса перераспределена. Вы пишете деинициализаторы с ключевым словом deinit, аналогичным о том, как intializers записываются с ключевым словом init. Deinitializers доступны только для типов классов.

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

Ответ 2

deinit {
    // perform the deinitialization
}

- правильный ответ для Swift "dealloc".

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

https://developer.apple.com/library/content/releasenotes/Foundation/RN-FoundationOlderNotes/index.html#X10_11Notes

NSNotificationCenter

В OS X 10.11 и iOS 9.0 NSNotificationCenter и NSDistributedNotificationCenter больше не будут отправлять уведомления зарегистрированным наблюдателям, которые могут быть освобождены. Если наблюдатель может быть сохранен как ссылка с низким уровнем обнуления, базовое хранилище будет хранить наблюдателя как слабое задание обнуления, альтернативно, если объект не может быть сохранен слабо (т.е. Он имеет собственный механизм сохранения/освобождения, который предотвратит время выполнения от возможности слабо хранить объект), он сохранит объект в качестве несимметричной ссылки на обнуление. Это означает, что наблюдатели не обязаны отказываться от регистрации в методе их освобождения. Следующее уведомление, которое будет направлено этому наблюдателю, обнаружит нулевую ссылку и автоматически отменяет регистрацию наблюдателя. Если объект может быть слабо указан, уведомления больше не будут отправляться наблюдателю во время освобождения; предыдущее поведение приема уведомлений во время dealloc все еще присутствует в случае нештатных обнуляющих опорных наблюдателей. Наблюдатели на основе блоков с помощью метода [NSNotificationCenter addObserverForName: object: queue: usingBlock] по-прежнему должны быть незарегистрированы, когда они больше не используются, поскольку система по-прежнему имеет сильную ссылку на этих наблюдателей. По-прежнему поддерживается снятие наблюдателей (либо слабо ссылка, либо ссылка на нуль). CFNotificationCenterAddObserver не соответствует этому поведению, поскольку наблюдатель не может быть объектом.

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

Ответ 3

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

  Swift автоматически освобождает ваши экземпляры, когда они больше не нужны, чтобы освободить ресурсы. Swift управляет памятью экземпляров с помощью автоматического подсчета ссылок (ARC), как описано в разделе Автоматический подсчет ссылок. Обычно вам не нужно выполнять ручную очистку, когда ваши экземпляры освобождаются. Однако, когда вы работаете с собственными ресурсами, вам может потребоваться выполнить дополнительную очистку самостоятельно. Например, если вы создаете пользовательский класс, чтобы открыть файл и записать в него некоторые данные, вам может потребоваться закрыть файл до того, как экземпляр класса будет освобожден.

Определения классов могут иметь не более одного деинициализатора на класс. Деинициализатор не принимает никаких параметров и записывается без скобок:

deinit {
    // perform the deinitialization
}

Ответ 4

Удаление наблюдателя необходимо до освобождения, иначе произойдет сбой. Это можно сделать с помощью

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

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

}

Ответ 5

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