The Right Place to Call .Removeobserver for Nsnotificationcenter = Swift Deinit()

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 NSNotificationCenternotifications 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:

  1. 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.

  2. 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 the deinit 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 from dealloc/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



Leave a reply



Submit