This is my first post. I'm Japanese iOS engineer (just became this month).
I have a trouble with removeObserver
method of NotificationCenter
in Swift 5.
I added observer to ViewController (VC) by using closure type addObserver
. I want to remove this Observer when VC's deinitialization has called.
I wrote NotificationCenter.default.removeObserver(self)
in VC's deinit
method. But, this seemed not to work for me.
What's the problem???
Additionally, if my code has memory leak problem, let me know how to fix it.
Here's piece of my code.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: nil) { [weak self] notification in
guard let self = self else { return }
self.loadWeather(notification.object)
}
}
deinit {
print(#function)
print("ViewController died")
NotificationCenter.default.removeObserver(self)
}
}
If you use the closure-based variant of addObserver, the token (not
self
) is the observer. The notification center has no knowledge at all aboutself
in this situation. The documentation is not super clear on this.
Meaning it's meaningless to do: NotificationCenter.default.removeObserver(self)
The docs recommend two ways:
Subscribe as you normally do:
let center = NSNotificationCenter.defaultCenter()
let mainQueue = NSOperationQueue.mainQueue()
self.localeChangeObserver = center.addObserverForName(NSCurrentLocaleDidChangeNotification, object: nil, queue: mainQueue) { (note) in
print("The user's locale changed to: \(NSLocale.currentLocale().localeIdentifier)")
}
Remove the observer at some point of code. NotificationCenter.default.removeObserver(self.localeChangeObserver)
eg through a function or in deinit
Remove the observer immediately after the first time it gets a callback
let center = NSNotificationCenter.defaultCenter()
let mainQueue = NSOperationQueue.mainQueue()
var token: NSObjectProtocol?
token = center.addObserverForName("OneTimeNotification", object: nil, queue: mainQueue) { (note) in
print("Received the notification!")
center.removeObserver(token!)
}
If you use the selector-based add, self
(there is no token) the observer. Having that said, you should avoid doing:
NotificationCenter.default.removeObserver(self)
because your code may not be the only code adding observers that involve the object. When removing an observer, remove it with the most specific detail possible. For example, if you used a name and object to register the observer, use removeObserver(_:name:object:)
with the name and object.
It's only safe to call removeObserver(something)
in the deinit
method, other than that don't use it use removeObserver(_:name:object:)
instead.
Calling removeObserver(self)
is incorrect outside deinit
, because you'd be removing all observations set for the object. Calling it inside deinit
isn't incorrect, but meaningless, because the object is to be deallocated immediately.
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!)
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.