为什么不对使用过NSNotificationCenter的对象进行调用,我在下面包含了我的代码的简单版本。在我创建一个观察通知的对象以及触发通知时,它会删除观察者的订阅。如果释放了对象,我也会删除订阅。但是,在为应用程序运行性能分析时,您可以看到在viewDidAppear完成后,测试对象的持久分配现在为零,应该已经释放。为什么会这样?
import UIKit
class ViewController: UIViewController {
var t: test?
override func viewWillAppear(animated: Bool) {
t = test()
fire()
t = nil
}
func fire() {
NSNotificationCenter.defaultCenter().postNotificationName("Hello",
object: nil)
}
}
class test {
var e: NSObjectProtocol?
init() {
e = NSNotificationCenter.defaultCenter().addObserverForName(
"Hello", object: nil, queue: NSOperationQueue.mainQueue(),
usingBlock: sayHello)
}
deinit {
if let e = e { NSNotificationCenter.defaultCenter().removeObserver(e) }
}
func sayHello(notification: NSNotification) {
if let e = e { NSNotificationCenter.defaultCenter().removeObserver(e) }
}
}
即使在Objective-C中我也会很感激,因为它也可能会回答这个问题。
非常感谢
答案 0 :(得分:5)
传递self
函数作为闭包参数将创建一个保留周期。
你正在做的是有效率的短手:
init() {
e = NSNotificationCenter.defaultCenter().addObserverForName("Hello", object: nil, queue: NSOperationQueue.mainQueue() { notification in
self.sayHello(notification)
}
}
正如您所见,此处正在捕捉self
。要解决这个问题,您应该在capture list中将self
定义为unowned
:
init() {
e = NSNotificationCenter.defaultCenter().addObserverForName("Hello", object: nil, queue: NSOperationQueue.mainQueue() { [unowned self] notification in
self.sayHello(notification)
}
}
这将阻止保留周期。
当您移除sayHello
中的观察者时,您也应该在移除观察者后将e
设置为nil
。
有关在NSNotificationCenter
上使用此方法时保留周期,捕获等的详细信息,请参阅this问题。
答案 1 :(得分:0)
你不能将自己添加为观察者而是另一个块。
BUT
然后你删除自己(虽然从未添加)但忘记了块
---所以:
self.observer = center.addObserverForName(didEnterBackground, object: nil, queue: nil) {
...
}
然后再
center.removeObserver(self.observer)