十、無事勿擾,有事通知(1)——NSNotification
概述
很久很久以前,有一只菜鳥正在美滋滋的擼著他的嵌入式C代碼。然而有一天,老板對菜鳥說:“別擼C了,從現在開始你就寫swift開發ios了。”菜鳥一臉懵逼,但還是照做了。
又有一天,菜蛋諂媚的對菜鳥說:“我的左腳小拇指突然發生了間歇性肌肉組織神經調控微紊亂,能不能幫忙拿個快遞?”菜鳥不屑道:“沒空!”
老板和菜鳥的關系叫做“調用”,菜蛋和菜鳥的關系叫做“通知”。
所謂“通知”,就是當對象A發生了狀態變化時,它將該信息變化發送給對此感興趣的其他對象,以便後者采取相應行為。
“通知”相對於“調用”的優點在於:在程序運行期間,被通知者可以選擇性的接收甚至拒絕通知者的消息以及動態的修改相應的動作,而“調用”則不行。
iOS存在2種實現通知的方式,一是KVO,二是NSNotification。這節我們就先來說說NSNotification。
概念及流程
Notification:通知信號標誌,以“name”作為其ID。
NotificationCenter:通知信號標誌管理中心,負責維護和分發Notification及其攜帶的數據。
使用流程如下(如下圖):
1. 首先創建1個NotificationCenter,然後使用該NotificationCenter的函數“addObserver”將Ob1、Ob2、Ob3和Notification:Name1進行綁定。
2. 當Sender想對Notification:Name1發送數據時,使用NotificationCenter的函數“post”將數據和Notification:Name1綁定發送。
3. NotificationCenter遍歷之前所有和Notification:Name1綁定過得Observer,並連帶Notification:Name1的數據調用各個Observer的回調函數。
舉個例子
紙上得來終覺淺,我們先來實現個例子。
我們創建3個label作為Observer和1個button作為Sender,3個label會監聽Notification消息,當接收到消息通知時,就打印收到的數據。button點擊後會觸發其發送消息。
1 import UIKit 2 3 class MyUILabel: UILabel { 4 5 varView Codesay:String = "..." 6 let userInfoKeyFly = "fly" 7 let userInfoKeyHeight = "height" 8 9 func setSay(say:String) { 10 self.say = say 11 } 12 13 func addObserver(notificationName: Notification.Name) { 14 NotificationCenter.default.addObserver(self, selector: #selector(callback(notification: )), name: notificationName, object: nil) 15 } 16 17 @objc func callback(notification: Notification) { 18 let userInfo = notification.userInfo as! [String:AnyObject] 19 let flyValue = userInfo[userInfoKeyFly] as! String 20 let heightValue = userInfo[userInfoKeyHeight] as! Int32 21 22 text = "\(say)(\(flyValue):\(heightValue)米)" 23 } 24 25 deinit { 26 NotificationCenter.default.removeObserver(self) 27 } 28 29 }
首先,我們自定義了Label,addObserver是其對外監聽消息的借口,callback為收到消息後的回調函數。此外還得添加析構函數deinit,以刪除其對消息的監聽,否則將發生內存泄漏。(註意:NotificationCenter.default是系統為APP創建的默認NotificationCenter)
1 import UIKit 2 3 4 class ViewController: UIViewController { 5 6 @IBOutlet weak var passerby1: MyUILabel! 7 @IBOutlet weak var passerby2: MyUILabel! 8 @IBOutlet weak var passerby3: MyUILabel! 9 10 let notificationName = Notification.Name(rawValue: "noob") 11 let userInfoKeyFly = "fly" 12 let userInfoKeyFlyValue = "high" 13 let userInfoKeyHeight = "height" 14 let userInfoKeyHeightValue = 1 15 16 override func viewDidLoad() { 17 super.viewDidLoad() 18 passerby1!.setSay(say: passerby1.text! + "我不信") 19 passerby2!.setSay(say: passerby2.text! + "我會信?") 20 passerby3!.setSay(say: passerby3.text! + "差點信了") 21 passerby1!.addObserver(notificationName: notificationName) 22 passerby2!.addObserver(notificationName: notificationName) 23 passerby3!.addObserver(notificationName: notificationName) 24 25 } 26 27 override func didReceiveMemoryWarning() { 28 super.didReceiveMemoryWarning() 29 // Dispose of any resources that can be recreated. 30 } 31 32 @IBAction func flyHeighAction(_ sender: UIButton) { 33 NotificationCenter.default.post(name: notificationName, object: self, userInfo: [userInfoKeyFly:userInfoKeyFlyValue, userInfoKeyHeight:userInfoKeyHeightValue]) 34 35 } 36 37 }View Code
再ViewController中,我們聲明了1個名為“noob”的Notification,在viewDidLoad時,我們使3個Label監聽了該Notification。flyHeightAction為Button的觸摸回調函數,它會使用NotificationCenter.default向“noob”Notification發送數據userInfo(1個字典數據)。
如果有管理上的需要,我們想創建自己的NotificationCenter,那麽只需要調用“NoficationCenter.init()”就可以了,比如:
我們通過擴展NotificationCenter來添加自己的NotificationCenter
1 extension NotificationCenter { 2 static let myNotificationCenter = NotificationCenter.init() 3 }
然後我們就可以將上例中的“default”都改為“myNotificationCenter”,得到的結果是一樣的。
源碼下載:https://pan.baidu.com/s/1EdOhpwI-APUvedW5XlMrEw
上一節 回目錄 下一節
十、無事勿擾,有事通知(1)——NSNotification