Where should I remove the observer for NSNotification
in Swift, since viewDidUnload
and dealloc()
are unavailable?
Use below method which functions same as dealloc
.
deinit {
// Release all resources
// perform the deinitialization
}
A deinitializer is called immediately before a class instance is deallocated. You write deinitializers with the deinit keyword, similar to how intializers are written with the init keyword. Deinitializers are only available on class types.
deinit
method for ViewControllerA will not be called when it will push ViewControllerB. –
Neubauer deinit
for ViewControllerA will be only called when it is not in navigation controller's stack. For example: Switching to rootViewController (if rootViewController is not ViewControllerA) –
Donaldson deinit
at all. Ideal place to call would func viewDidDisappear(_ animated: Bool)
–
Annihilation deinit
not getting called. It's more of how we implementation the solution. –
Annihilation As of iOS 9 (and OS X 10.11), you don't need to remove observers yourself, if you're not using block based observers though. The system will do it for you, since it uses zeroing-weak references for observers, where it can.
And if you are using block based observers, make sure you capture self weakly using [weak self]
in the closure's capture list, and remove observer in deinit
method. If you don't use weak reference to self, deinit
method (and thus removal of that observer) will never be called since Notification Center will hold a strong reference to it indefinitely.
More info can be found at Foundation Release Notes for OS X v10.11 and iOS 9.
If the observer is able to be stored as a zeroing-weak reference the underlying storage will store the observer as a zeroing weak reference, alternatively if the object cannot be stored weakly (i.e. it has a custom retain/release mechanism that would prevent the runtime from being able to store the object weakly) it will store the object as a non-weak zeroing reference. This means that observers are not required to un-register in their deallocation method.
Block based observers via the -[NSNotificationCenter addObserverForName: object: queue: usingBlock] method still need to be un-registered when no longer in use since the system still holds a strong reference to these observers.
delegate = nil
in dealloc()
method. Does it work the same from now? –
Donaldson self
but rather the observer is the return value from the addObserver
call –
Columnist Use below method which functions same as dealloc
.
deinit {
// Release all resources
// perform the deinitialization
}
A deinitializer is called immediately before a class instance is deallocated. You write deinitializers with the deinit keyword, similar to how intializers are written with the init keyword. Deinitializers are only available on class types.
deinit
method for ViewControllerA will not be called when it will push ViewControllerB. –
Neubauer deinit
for ViewControllerA will be only called when it is not in navigation controller's stack. For example: Switching to rootViewController (if rootViewController is not ViewControllerA) –
Donaldson deinit
at all. Ideal place to call would func viewDidDisappear(_ animated: Bool)
–
Annihilation deinit
not getting called. It's more of how we implementation the solution. –
Annihilation You can use three methods:
after
popViewController
, backnavigationController
ordismissViewControllerAnimated
:deinit { print("Remove NotificationCenter Deinit") NSNotificationCenter.defaultCenter().removeObserver(self) }
viewDidDisappear
, remove after it is already the next view controller:override func viewDidDisappear(animated: Bool) { NSNotificationCenter.defaultCenter().removeObserver(self) }
viewWillDisappear
- before opening the next view:override func viewWillDisappear(animated: Bool) { NSNotificationCenter.defaultCenter().removeObserver(self) }
Swift 5.0 syntax:
NotificationCenter.default.removeObserver(self)
In Swift 4.2, this is one of the way you can remove observer
deinit {
NotificationCenter.default.removeObserver(self, name: Notification.Name.Identifier, object: nil)
}
setup addObserver notification in viewDidLoad class
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(didReceivedItemDetail), name: Notification.Name.Identifier, object: nil)
}
Swift provides a deinit method that is called on instances of classes before they are destroyed.
I also want to point out that you should use this method:
func addObserver(_ observer: Any, selector aSelector: Selector, name aName: NSNotification.Name?, object anObject: Any?)
Instead of
func addObserver(forName name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol
The latter will not remove the observer (Ran into this problem recently). The former will remove the observer if you are using iOS9.
dealloc
method. –
Varhol Swift 5
I have a chat application, so whenever I go from my ChatLogViewController to some other viewController and then comeback, I have 1 extra Observer of my keyboard notification. To remove that I remove all the observers when I change my viewController or disappear from my chatLogViewController.
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
deinit {
//Remove Observer
NotificationCenter.default.removeObserver(self)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
It is also good if you add your observer in viewWillAppear()
and remove them in viewWillDisappear()
In some special cases, You should add your observer in
func viewWillAppear(_ animated: Bool)
Because if you have a popup view controller in your main view controller when it shows up, you don't want remove observers from the Notification Center. If you use
func viewDidDisappear(_ animated: Bool)
you will missed notifications after the popup showed up!
SO
You should reset subscription when
func viewWillAppear(_ animated: Bool)
func triggered.
© 2022 - 2024 — McMap. All rights reserved.