The right place to call .removeObserver for NSNotificationCenter = Swift deinit()?
It really depends on the role of the class where you subscribe to NSNotificationCenter notifications. If you are subscribing in:
UIView
Then you should unsubscribe as soon as view gets invisible to the user. To save CPU cycles and not consume resources while user does not see the view.
UIViewController
Here it also depends on kind of action that you are going to perform in response to notification. If it is just a UI adjustment that you should unsubscribe as soon as view controller disappears from the screen.
You App Service layer
Here it is OK to have .removeObserver
inside deinit(). however even here I tend to suggest you to be more explicit about when you subscribe and unsubscribe from NSNotificationCenter
notifications and put them in start and stop methods of your service.
Swift - Is the correct place to call .removeObserver always deinit()?
In your case you should remove observers in viewWillDisappear
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: UIApplication.willEnterForegroundNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: UIApplication.didEnterBackgroundNotification, object: nil)
}
Where to remove observer for NSNotification in Swift?
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.
Swift Deinitializer
when to call removeObserver for nsnotificationcenter
A couple of observations:
I infer from your code comment that you are contemplating removing the observer inside the selector for that particular notification. That is a fine practice.
I'd be wary about just calling
removeObserver
, though, because that will remove all observers that you may have set up. If you are calling this inside the routine that is the selector for a particular notification, then I might be inclined to remove only that particular notification:NSNotificationCenter.defaultCenter().removeObserver(self, name: NotificationConstants.pvpConnEstablishedString, object: nil)
Yes, at this point, you may only be observing a single notification, so this may feel unnecessary, but if at some future date you add completely separate notification handling code for a different notification, you want to make sure that you don't accidentally remove all observers when handling a particular notification.
You might want to be sensitive to the possibility that this view controller may be dismissed before the notification comes in. In that case, it might be prudent to also add
removeObserver
in thedeinit
method for the view controller.In this case, the simple
removeObserver(self)
is prudent (because it's reasonable to remove all observers when the view controller is deallocated).
Where is the right place to remove notification observers in Swift 2?
If you need this setObserver
extension, you are very likely doing something wrong. You should be able to balance your registration and removal easily. If you can't, your notification management is very likely too complicated or in the wrong place.
Typically the correct place to add observations is in viewWillAppear
(or viewDidAppear
, either is fine), and remove them in viewDidDisappear
(or viewWillDisappear
). This ensures that you do not receive notifications while you are offscreen, even if the view controller still exists (which is common).
If your view controller requires that it receive notifications while it is offscreen, then you have a design problem. View controllers should only manage onscreen views. If they're doing anything else, you have put too much of the model into the controller.
As @rmaddy notes, your specific problem is likely that you have two instances of this view controller. That's may be fine or it might be a mistake (it depends on how the view controller works). But if you balance adding and removing your registration when going on and offscreen, that part will be fine.
How to safely removeObserver (Swift)
I think you should use code
NSNotificationCenter.defaultCenter().removeObserver(self)
Explain:
You have mistake here: You are using NSNotification & NSNotificationCenter so you have to using this code above to remove observe.
you have use code for KVO to remove observer so it will wrong.
More detail you can read at here. Key-Value-Observing
Should deinit be overridden to remove observers in Swift?
As of iOS 9 , 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.
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.
Apple Docs
and for super.deinit() apple says
Deinitializers are called automatically, just before instance
deallocation takes place. You are not allowed to call a deinitializer
yourself. Superclass deinitializers are inherited by their subclasses,
and the superclass deinitializer is called automatically at the end of
a subclass deinitializer implementation. Superclass deinitializers are
always called, even if a subclass does not provide its own
deinitializer.
swift docs
Objective-C: Where to remove observer for NSNotification?
The generic answer would be "as soon as you no longer need the notifications". This is obviously not a satisfying answer.
I'd recommend, that you add a call [notificationCenter removeObserver: self]
in method dealloc
of those classes, which you intend to use as observers, as it is the last chance to unregister an observer cleanly. This will, however, only protect you against crashes due to the notification center notifying dead objects. It cannot protect your code against receiving notifications, when your objects are not yet/no longer in a state in which they can properly handle the notification. For this... See above.
Edit (since the answer seems to draw more comments than I would have thought) All I am trying to say here is: it's really hard to give general advice as to when it's best to remove the observer from the notification center, because that depends:
- On your use case (Which notifications are observed? When do they get send?)
- The implementation of the observer (When is it ready to receive notifications? When is it no longer ready?)
- The intended life-time of the observer (Is it tied to some other object, say, a view or view controller?)
- ...
So, the best general advice I can come up with: to protect your app. against at least one possible failure, do the removeObserver:
dance in dealloc
, since that's the last point (in the object's life), where you can do that cleanly. What this does not mean is: "just defer the removal until dealloc
is called, and everything will be fine". Instead, remove the observer as soon as the object is no longer ready (or required) to receive notifications. That is the exact right moment. Unfortunately, not knowing the answers to any of the questions mentioned above, I cannot even guess, when that moment would be.
You can always safely removeObserver:
an object multiple times (and all but the very first call with a given observer will be nops). So: think about doing it (again) in dealloc
just to be sure, but first and foremost: do it at the appropriate moment (which is determined by your use case).
How to removeObserver in Swift 5 using addObserver closure method
Set your observer object to current view controller.
From apple doc.s, object is
The object whose notifications the observer wants to receive; that is,
only notifications sent by this sender are delivered to the observer.
NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification,
object: self,
queue: nil) { [weak self] notification in
guard let self = self else { return }
self.loadWeather(notification.object)
}
Removing observer from NotificationCenter
deinit {
NotificationCenter.default.removeObserver(self)
}
ANOTHER WAY
You can also make copy of Notification Observer object and remove it from NotificationCenter
in deinit
.
let notificationCenter = NotificationCenter.default
var loadWeatherObserver: NSObjectProtocol?
override func viewDidLoad() {
super.viewDidLoad()
loadWeatherObserver = notificationCenter.addObserver(forName: UIApplication.didBecomeActiveNotification,
object: nil,
queue: nil) { [weak self] notification in
guard let self = self else { return }
self.loadWeather(notification.object)
}
}
deinit {
if (loadWeatherObserver != nil) {
notificationCenter.removeObserver(loadWeatherObserver!)
}
}
Is removing a NotificationCenter observer that was created with closure syntax by name adequate?
You absolutely need to store the return value in a property and remove that later on.
From https://developer.apple.com/reference/foundation/nsnotificationcenter/1411723-addobserverforname:
Return Value
An opaque object to act as the observer.
When you call any one of the removeObserver
methods, the first parameter is the observer to remove. When you set up a block to respond to a notification, self
is not the observer, NSNotificationCenter
creates its own observer object behind the scenes and returns it to you.
Note: as of iOS 9, you are no longer required to call
removeObserver
fromdealloc
/deinit
, as that will happen automatically when the observer goes away. So, if you're only targeting iOS 9, this may all just work, but if you're not retaining the returned observer at all, the notification could be removed before you expect it to be. Better safe than sorry.
Related Topics
How to Pass a Reference to a Boolean Rather Than Its Value
What Does T Equals T Mean in Generics
See Characters in an Nscharacterset (Swift)
I Can't Include ' Symbol to Regular Expressions
Trouble with Non-Escaping Closures in Swift 3
Swift Error Comparing Two Arrays of Optionals
Swift Protocol with Variadic Property
Using Foreach with a String Array - [String] Has No Member 'Identified'
Swift: For-In Loop Requires '[Deepspeechtokenmetadata]' to Conform to 'Sequence'
Swift: Uploading Image to Firebase Cloud Storage When User Closes App
Failed to Obtain a Cell from Its Datasource with Swift 3
Alternative to Switch Statement in Swiftui Viewbuilder Block
Is There a Number Type with Bigger Capacity Than U_Long/Uint64 in Swift
Swift Protocol Property in Protocol - Candidate Has Non-Matching Type
Replace Exactly One Pixel in an Image and Put It in Another Image via Swift
I Have Trouble Using Cornerradius and Borders on a Textfield in Swiftui