如何使用 addObserver 闭包方法移除 Swift 5 中的 Observer
How to removeObserver in Swift 5 using addObserver closure method
这是我的第一个 post。
我是日本人 iOS 工程师(这个月刚成为)。
我在 Swift 5 中使用 NotificationCenter
的 removeObserver
方法有问题。
我通过使用闭包类型 addObserver
将观察者添加到 ViewController (VC)。
我想在 VC 的取消初始化调用时删除这个 Observer。
我在VC的deinit
方法中写了NotificationCenter.default.removeObserver(self)
。但是,这似乎对我不起作用。
有什么问题???
此外,如果我的代码有内存泄漏问题,请告诉我如何修复它。
这是我的一段代码。
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)
}
}
将您的观察者对象设置为当前视图控制器。
来自apple doc.s,对象是
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)
}
正在从 NotificationCenter
中删除观察者
deinit {
NotificationCenter.default.removeObserver(self)
}
另一种方式
您还可以复制 Notification Observer 对象并将其从 deinit
中的 NotificationCenter
中删除。
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!)
}
}
Closure-based addObserver
If you use the closure-based variant of addObserver, the token (not self
) is
the observer. The notification center has no knowledge at all about
self
in this situation. The documentation is not super clear on
this.
意思是这样做没有意义:NotificationCenter.default.removeObserver(self)
docs推荐两种方式:
正常方式
像往常一样订阅:
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)")
}
在代码的某个位置移除观察者。
NotificationCenter.default.removeObserver(self.localeChangeObserver)
例如通过函数或 deinit
单次订阅
第一次收到回调后立即移除观察者
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!)
}
Selector-based addObserver
如果使用基于选择器的添加,self
(没有标记)观察者。话虽如此,你应该避免做:
NotificationCenter.default.removeObserver(self)
因为您的代码可能不是唯一添加涉及对象的观察者的代码。删除观察者时,请尽可能详细地删除它。例如,如果您使用名称和对象来注册观察者,请将 removeObserver(_:name:object:)
与名称和对象一起使用。
只有在 deinit
方法中调用 removeObserver(something)
才是安全的,除此之外不要使用它,而是使用 removeObserver(_:name:object:)
。
在 deinit
之外调用 removeObserver(self)
是不正确的,因为您将删除为该对象设置的所有观察值。在 deinit
中调用它并没有错,但是没有意义,因为对象将被立即释放。
这是我的第一个 post。 我是日本人 iOS 工程师(这个月刚成为)。
我在 Swift 5 中使用 NotificationCenter
的 removeObserver
方法有问题。
我通过使用闭包类型 addObserver
将观察者添加到 ViewController (VC)。
我想在 VC 的取消初始化调用时删除这个 Observer。
我在VC的deinit
方法中写了NotificationCenter.default.removeObserver(self)
。但是,这似乎对我不起作用。
有什么问题???
此外,如果我的代码有内存泄漏问题,请告诉我如何修复它。
这是我的一段代码。
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)
}
}
将您的观察者对象设置为当前视图控制器。
来自apple doc.s,对象是
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)
}
正在从 NotificationCenter
deinit {
NotificationCenter.default.removeObserver(self)
}
另一种方式
您还可以复制 Notification Observer 对象并将其从 deinit
中的 NotificationCenter
中删除。
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!)
}
}
Closure-based addObserver
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.
意思是这样做没有意义:NotificationCenter.default.removeObserver(self)
docs推荐两种方式:
正常方式
像往常一样订阅:
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)")
}
在代码的某个位置移除观察者。
NotificationCenter.default.removeObserver(self.localeChangeObserver)
例如通过函数或 deinit
单次订阅
第一次收到回调后立即移除观察者
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!)
}
Selector-based addObserver
如果使用基于选择器的添加,self
(没有标记)观察者。话虽如此,你应该避免做:
NotificationCenter.default.removeObserver(self)
因为您的代码可能不是唯一添加涉及对象的观察者的代码。删除观察者时,请尽可能详细地删除它。例如,如果您使用名称和对象来注册观察者,请将 removeObserver(_:name:object:)
与名称和对象一起使用。
只有在 deinit
方法中调用 removeObserver(something)
才是安全的,除此之外不要使用它,而是使用 removeObserver(_:name:object:)
。
在 deinit
之外调用 removeObserver(self)
是不正确的,因为您将删除为该对象设置的所有观察值。在 deinit
中调用它并没有错,但是没有意义,因为对象将被立即释放。