Apple 在 iOS4 中添加 addObserverForName 方法几莽,給予開發(fā)者可以在block中處理 Notification 通知的便捷方法银觅。
但是究驴,在實(shí)際應(yīng)用中匀伏,卻比原有的 Selector 方法更復(fù)雜够颠,甚至,一不小心就造成循環(huán)引用蛉抓,內(nèi)存得不到釋放巷送。
這個方法的使用方法是這樣的
class ViewController: UIViewController {
weak var nameObserver: NSObjectProtocol?
override func viewDidLoad() {
super.viewDidLoad()
nameObserver = NSNotificationCenter.defaultCenter().addObserverForName("Name", object: nil, queue: NSOperationQueue.mainQueue()) { (_) -> Void in
print("some one call me!")
}
}
}
像上面這樣使用驶忌,真是一點(diǎn)問題都沒有! 但是笑跛,如果你要在block上使用self關(guān)鍵字的話付魔,那就會造成循環(huán)引用(其實(shí)不算是循環(huán)引用,只要你在某個時間點(diǎn)飞蹂,能把observer釋放掉几苍,也是OK的),這個ViewController永遠(yuǎn)不會被釋放陈哑。
class ViewController: UIViewController {
weak var nameObserver: NSObjectProtocol?
deinit {
print("dealloced") // 析構(gòu)方法永遠(yuǎn)不會被執(zhí)行
}
override func viewDidLoad() {
super.viewDidLoad()
nameObserver = NSNotificationCenter.defaultCenter().addObserverForName("Name", object: nil, queue: NSOperationQueue.mainQueue()) { (_) -> Void in
print("some one call me! -- view:\(self.view)")
}
}
}
解決方法很簡單妻坝,使用weak self就可以了
class ViewController: UIViewController {
weak var nameObserver: NSObjectProtocol?
deinit {
print("dealloced") // 這樣就可以走到析構(gòu)方法了
}
override func viewDidLoad() {
super.viewDidLoad()
weak var welf = self
nameObserver = NSNotificationCenter.defaultCenter().addObserverForName("Name", object: nil, queue: NSOperationQueue.mainQueue()) { (_) -> Void in
if let welf = welf {
print("some one call me! -- view:\(welf.view)")
}
}
}
}
等等,你以為到這里惊窖,就結(jié)束了嗎惠勒? 要記得,這個 Observer 其實(shí)還被 NSNotificationCenter 引用著,他也是不會釋放的,最明顯的體現(xiàn)就是,就算你的ViewController被釋放了,block中的代碼塊仍然會被執(zhí)行材鹦。 解決方法也很簡單。
class ViewController: UIViewController {
weak var nameObserver: NSObjectProtocol?
deinit {
if let nameObserver = nameObserver {
NSNotificationCenter.defaultCenter().removeObserver(nameObserver) // 那我們就把它釋放掉好了
}
print("dealloced") // 這樣就可以走到析構(gòu)方法了
}
override func viewDidLoad() {
super.viewDidLoad()
weak var welf = self
nameObserver = NSNotificationCenter.defaultCenter().addObserverForName("Name", object: nil, queue: NSOperationQueue.mainQueue()) { (_) -> Void in
if let welf = welf {
print("some one call me! -- view:\(welf.view)")
}
}
}
}