Apple 在 iOS4 中添加 addObserverForName 方法,給予開發者可以在block中處理 Notification 通知的便捷方法。
但是,在實際應用中,卻比原有的 Selector 方法更復雜,甚至,一不小心就造成循環引用,內存得不到釋放。
這個方法的使用方法是這樣的
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!")
}
}
}
像上面這樣使用,真是一點問題都沒有! 但是,如果你要在block上使用self關鍵字的話,那就會造成循環引用(其實不算是循環引用,只要你在某個時間點,能把observer釋放掉,也是OK的),這個ViewController永遠不會被釋放。
class ViewController: UIViewController {
weak var nameObserver: NSObjectProtocol?
deinit {
print("dealloced") // 析構方法永遠不會被執行
}
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") // 這樣就可以走到析構方法了
}
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)")
}
}
}
}
等等,你以為到這里,就結束了嗎? 要記得,這個 Observer 其實還被 NSNotificationCenter 引用著,他也是不會釋放的,最明顯的體現就是,就算你的ViewController被釋放了,block中的代碼塊仍然會被執行。 解決方法也很簡單。
class ViewController: UIViewController {
weak var nameObserver: NSObjectProtocol?
deinit {
if let nameObserver = nameObserver {
NSNotificationCenter.defaultCenter().removeObserver(nameObserver) // 那我們就把它釋放掉好了
}
print("dealloced") // 這樣就可以走到析構方法了
}
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)")
}
}
}
}