使用NSNotificationCenter时,ARC无法正常工作

lui*_*uis 1 nsnotificationcenter ios swift

为什么不在使用NSNotificationCenter的对象上调用deist,我在下面包含了我的代码的简单版本.在我创建一个观察通知的对象以及触发通知时,它会删除观察者的订阅.如果释放了对象,我也会删除订阅.但是,在为应用程序运行性能分析时,您可以看到在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) }
    }

}
Run Code Online (Sandbox Code Playgroud)

即使在Objective-C中,我也会很感激,因为它也可能会回答这个问题.

非常感谢你

Ric*_*ich 5

传递self作为闭包参数的函数将创建保留周期.你正在做的是有效率的短手:

init() {
   e = NSNotificationCenter.defaultCenter().addObserverForName("Hello", object: nil, queue: NSOperationQueue.mainQueue() { notification in 
      self.sayHello(notification) 
   }
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到self的那样被捕获.为了解决这个问题,你应该定义selfunowned捕获列表:

init() {
   e = NSNotificationCenter.defaultCenter().addObserverForName("Hello", object: nil, queue: NSOperationQueue.mainQueue() { [unowned self] notification in 
      self.sayHello(notification) 
   }
}
Run Code Online (Sandbox Code Playgroud)

这将阻止保留周期.

正如您删除观察者sayHello,你也应该设置enil在那里移除观察者后了.

有关使用此方法时保留周期,捕获等的详细信息,请参阅问题NSNotificationCenter.