iOS 无法删除通知观察器。 Deinit 没有被调用
iOS unable to remove Notification observer. Deinit not getting called
我有一个类似于您在下面看到的 UIView:
class ViewTaskViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
subscribeToNotifications()
}
func subscribeToNotifications() {
let notification = NotificationCenter.default
notification.addObserver(forName: Notification.Name(rawValue: "TimerUpdated"), object: nil, queue: nil, using: handleUpdateTimer)
print("Subscribed to NotificationCenter in ViewTaskViewController")
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
print("TUFU TUFU TUFU")
NotificationCenter.default.removeObserver(self)
}
deinit {
print("DENINT")
}
@objc func handleUpdateTimer(notification: Notification) {
if let userInfo = notification.userInfo, let timeInSeconds = userInfo["timeInSeconds"] as? Int {
withUnsafePointer(to: &self.view) {
print("We got timeeeeee \(timeInSeconds) \([=11=])")
}
//do something here....
}
}
}
我遇到的问题是,当用户点击后退按钮并 returns 到另一个 viewController 时,我无法从这个特定的 UIView 中删除观察者。
ViewWillDisppear
被调用但 deinit
没有被调用。奇怪的是,如果我们从 viewDidLoad()
中删除 subscribeToNotifications()
,那么 deinit
就会被调用。
另一个问题与内存泄漏有关。正如您在下面的屏幕截图中所看到的,当视图确实订阅通知并且用户 leaves/re-enters 视图时,内存使用量增加。
现在与注释掉 subscribeToNotifications()
时相比,内存使用量没有增加,只有一个 viewController 实例。
结论是,UIView 的新实例的通知订阅创建之间似乎存在关联,因此 deinit
未被调用。
我想知道是否有一种方法可以取消初始化视图并取消订阅通知。
如果您需要更多信息,请告诉我。 :)
我发现 removeObserver() 只有在您使用此版本的 addObserver() 时才有效
notification.addObserver(self, selector:#selector(self.handleUpdateTimer), name: Notification.Name(rawValue: "TimerUpdated"), object: nil)
我猜你在原始版本中并没有真正指出观察者是谁。
正如@Spads 所说,您可以使用
NotificationCenter.default.addObserver(self, selector: #selector(subscribeToNotifications), name: NSNotification.Name(rawValue: "TimerUpdate"), object: nil)
或您已有的那个。
你可以通过它的名字或者它的引用来删除你的通知
NotificationCenter.default.removeObserver(self, name: "TimerUpdate", object: nil)
如果您在 class 的顶部声明了您的通知,那么您可以直接传递要在您的案例中删除的通知的引用 notification
NotificationCenter.default.removeObserver(notification)
您应该将新添加的观察者存储在不透明对象 (NSObjectProtocol
) 中,然后调用 NotificationCenter.default.removeObserver(self.nameOfObserver)
我有一个类似于您在下面看到的 UIView:
class ViewTaskViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
subscribeToNotifications()
}
func subscribeToNotifications() {
let notification = NotificationCenter.default
notification.addObserver(forName: Notification.Name(rawValue: "TimerUpdated"), object: nil, queue: nil, using: handleUpdateTimer)
print("Subscribed to NotificationCenter in ViewTaskViewController")
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
print("TUFU TUFU TUFU")
NotificationCenter.default.removeObserver(self)
}
deinit {
print("DENINT")
}
@objc func handleUpdateTimer(notification: Notification) {
if let userInfo = notification.userInfo, let timeInSeconds = userInfo["timeInSeconds"] as? Int {
withUnsafePointer(to: &self.view) {
print("We got timeeeeee \(timeInSeconds) \([=11=])")
}
//do something here....
}
}
}
我遇到的问题是,当用户点击后退按钮并 returns 到另一个 viewController 时,我无法从这个特定的 UIView 中删除观察者。
ViewWillDisppear
被调用但 deinit
没有被调用。奇怪的是,如果我们从 viewDidLoad()
中删除 subscribeToNotifications()
,那么 deinit
就会被调用。
另一个问题与内存泄漏有关。正如您在下面的屏幕截图中所看到的,当视图确实订阅通知并且用户 leaves/re-enters 视图时,内存使用量增加。
现在与注释掉 subscribeToNotifications()
时相比,内存使用量没有增加,只有一个 viewController 实例。
deinit
未被调用。
我想知道是否有一种方法可以取消初始化视图并取消订阅通知。
如果您需要更多信息,请告诉我。 :)
我发现 removeObserver() 只有在您使用此版本的 addObserver() 时才有效
notification.addObserver(self, selector:#selector(self.handleUpdateTimer), name: Notification.Name(rawValue: "TimerUpdated"), object: nil)
我猜你在原始版本中并没有真正指出观察者是谁。
正如@Spads 所说,您可以使用
NotificationCenter.default.addObserver(self, selector: #selector(subscribeToNotifications), name: NSNotification.Name(rawValue: "TimerUpdate"), object: nil)
或您已有的那个。 你可以通过它的名字或者它的引用来删除你的通知
NotificationCenter.default.removeObserver(self, name: "TimerUpdate", object: nil)
如果您在 class 的顶部声明了您的通知,那么您可以直接传递要在您的案例中删除的通知的引用 notification
NotificationCenter.default.removeObserver(notification)
您应该将新添加的观察者存储在不透明对象 (NSObjectProtocol
) 中,然后调用 NotificationCenter.default.removeObserver(self.nameOfObserver)