Где убрать наблюдателя для NSNotification в Swift?

Где я должен удалить наблюдателя для NSNotification в Свифт, так как viewDidUnload а также dealloc() недоступны?

11 ответов

Решение

Используйте метод ниже, который работает так же, как dealloc,

deinit {
    // Release all resources
    // perform the deinitialization
}

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

Swift Deinitializer

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

И если вы используете наблюдателей на основе блоков, убедитесь, что вы слабо фиксируете себя, используя [weak self] в списке захвата закрытия и удалить наблюдателя в deinit метод. Если вы не используете слабую ссылку на себя, deinit метод (и, следовательно, удаление этого наблюдателя) никогда не будет вызван, так как Центр уведомлений будет постоянно ссылаться на него бесконечно.

Дополнительная информация может быть найдена в Основных примечаниях к выпуску для OS X v10.11 и iOS 9.

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

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

Вы можете использовать три метода:

1 - после popViewControllerназад navigationController или же dismissViewControllerAnimated:

deinit {
        print("Remove NotificationCenter Deinit")
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }

или же

2 - viewDidDisappear, удалите после того, как это уже следующий вид контроллера:

override func viewDidDisappear(animated: Bool) {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }

или же

3 - viewWillDisappear - до открытия следующего вида:

override func viewWillDisappear(animated: Bool) {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

Синтаксис Swift 3.0:

NotificationCenter.default.removeObserver(self)

В Swift 4.2 это один из способов удаления наблюдателя.

deinit {
    NotificationCenter.default.removeObserver(self, name: Notification.Name.Identifier, object: nil)
}

настроить уведомление addObserver в классе viewDidLoad

override func viewDidLoad() {
    super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(didReceivedItemDetail), name: Notification.Name.Identifier, object: nil)
}

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

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

Я также хочу отметить, что вы должны использовать этот метод:

func addObserver(_ observer: Any, selector aSelector: Selector, name aName: NSNotification.Name?, object anObject: Any?)

Вместо

func addObserver(forName name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol

Последний не удалит наблюдателя (столкнулся с этой проблемой недавно). Первый из них удалит наблюдателя, если вы используете iOS9.

      deinit {
    //Remove Observer 
    NotificationCenter.default.removeObserver(self)
}

Swift 5

У меня есть приложение чата, поэтому всякий раз, когда я перехожу из своего ChatLogViewController к другому viewController, а затем возвращаюсь, у меня есть 1 дополнительный наблюдатель для моего уведомления с клавиатуры. Чтобы удалить это, я удаляю всех наблюдателей, когда меняю свой viewController или исчезаю из моего chatLogViewController.

override func viewDidDisappear(_ animated: Bool) {    
    super.viewDidDisappear(animated)

    NotificationCenter.default.removeObserver(self)
}
deinit {
    NotificationCenter.default.removeObserver(self)
}

Также хорошо, если вы добавите своего наблюдателя в viewWillAppear() и удалите их в viewWillDisappear()

В некоторых особых случаях вам следует добавить своего наблюдателя в


Потому что, если у вас есть контроллер всплывающего представления в вашем главном контроллере представления , когда он появляется, вы не хотите удалять наблюдателей из Центра уведомлений . Если вы используете

      func viewDidDisappear(_ animated: Bool)

вы пропустите уведомления после появления всплывающего окна!

ТАК

Вам следует сбросить подписку, когда

      func viewWillAppear(_ animated: Bool)

функция сработала.

Другие вопросы по тегам