【发布时间】:2017-10-11 16:31:37
【问题描述】:
我有一个类似于您在下面看到的 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) \($0)")
}
//do something here....
}
}
}
我遇到的问题是,当用户点击后退按钮并返回到另一个 viewController 时,我无法从这个特定的 UIView 中删除观察者。
ViewWillDisppear 被调用但deinit 未被调用。奇怪的是,如果我们从viewDidLoad() 中删除subscribeToNotifications(),那么会调用deinit。
另一个问题与内存泄漏有关。正如您在下面的屏幕截图中看到的,当视图确实订阅了通知并且用户离开/重新进入视图时,内存使用量会增加。
现在比较一下subscribeToNotifications() 被注释掉时,内存使用量没有增加,只有一个viewController 实例。
结论是,通知订阅创建 UIView 的新实例之间似乎存在相关性,因此未调用 deinit。
我想知道是否有一种方法可以取消初始化视图并取消订阅通知。
如果您需要更多信息,请告诉我。 :)
【问题讨论】:
-
您正在使用的
addObserver方法的文档说:“要取消注册观察,您将 此方法返回的对象传递给 removeObserver(_:)。”相反,您似乎假设self是注册对象。
标签: ios swift memory-leaks nsnotification deinit