Dai*_*shi 5 memory-management nsnotificationcenter ios swift swift5
这是我的第一篇文章。我是日本的 iOS 工程师(这个月刚入职)。
我在 Swift 5 中的removeObserver方法有问题NotificationCenter。
我使用闭包类型向 ViewController (VC) 添加了观察者addObserver。当 VC 的取消初始化调用时,我想删除这个观察者。
我NotificationCenter.default.removeObserver(self)用VC的deinit方法写的。但是,这似乎对我不起作用。
有什么问题???
此外,如果我的代码有内存泄漏问题,请告诉我如何修复它。
这是我的一段代码。
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)
}
}
Run Code Online (Sandbox Code Playgroud)
Hon*_*ney 12
如果您使用addObserver的基于闭包的变体,则令牌(not
self) 是观察者。通知中心对self这种情况一无所知 。文档对此不是很清楚。
这意味着这样做毫无意义: NotificationCenter.default.removeObserver(self)
该文档推荐两种方法:
像往常一样订阅:
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)")
}
Run Code Online (Sandbox Code Playgroud)
在代码的某个点移除观察者。
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!)
}
Run Code Online (Sandbox Code Playgroud)
如果使用基于选择器的添加,self(没有标记)观察者。话虽如此,你应该避免这样做:
NotificationCenter.default.removeObserver(self)
Run Code Online (Sandbox Code Playgroud)
因为您的代码可能不是唯一添加涉及该对象的观察者的代码。移除观察者时,尽可能以最具体的细节移除它。例如,如果您使用名称和对象来注册观察者,请removeObserver(_:name:object:)与名称和对象一起使用。
只有removeObserver(something)在deinit方法中调用是安全的,除此之外不要使用它removeObserver(_:name:object:)而是使用它。
removeObserver(self)外部调用不正确deinit,因为您将删除为该对象设置的所有观察值。在内部调用它deinit并没有错,而是毫无意义,因为该对象将立即被释放。
将观察者对象设置为当前视图控制器。
来自苹果文档,对象是
观察者想要接收其通知的对象;也就是说,只有该发送者发送的通知才会传递给观察者。
NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification,
object: self,
queue: nil) { [weak self] notification in
guard let self = self else { return }
self.loadWeather(notification.object)
}
Run Code Online (Sandbox Code Playgroud)
从中删除观察者NotificationCenter
deinit {
NotificationCenter.default.removeObserver(self)
}
Run Code Online (Sandbox Code Playgroud)
其他方式
您还可以复制通知观察者对象并将其从NotificationCenter中删除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!)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4061 次 |
| 最近记录: |