2020年6月17日 星期三

[iOS - Swift] NotificationCenter

消息通知機制,可能有時候你會希望某個事情發生時,另外一個物件或頁面想到得知訊息。
舉一個生活上的例子,你訂閱了某個粉絲團,如果粉絲團發布一個訊息時,你可以收到。‌
首先你必須先加入觀察者,並且設定對應的Key與方法
///加入觀察者
NotificationCenter.default.addObserver(self,
                                       selector: #selector(ViewController.test),
                                       name: NSNotification.Name("Test123"),
                                       object: nil)
對應的方法
@objc private func test() {
    print("Hello Test!")
}
有一點像是Target - Action的形式,透過selector來指定要執行的方法。
接下來你只需要對通知中心發送通知,就可以觸發這個方法。

///發送訊息
NotificationCenter.default.post(name: NSNotification.Name("Test123"), object: nil)

接下來,你可以試著增加一個Class,並且也加入觀察者,Key使用相同的文字。

class MyClass {
    
    func addObserver() {
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(MyClass.test),
                                               name: NSNotification.Name("Test123"),
                                               object: nil)
    }
    
    @objc private func test() {
        print("My Class Test")
    }
}

接著執行一樣的程式碼試試看,你會發現兩邊都被觸發了,因為Key是相同的,所以他視為同樣的事件,因此兩邊都被觸發了。‌
知道了以上的特性,使用NotificationCenter時必須要小心,Key可能命名的獨一無二一點,若是與其他人相同,可能會發生意想不到的事情。
發送通知時,可以夾帶屬性,使用UserInfo這個參數就可以了,‌
首先我們把接收的方法改一下,並且將加入觀察者的方法也改了一下。
///加入觀察者
NotificationCenter.default.addObserver(self,
                                       selector: #selector(ViewController.test(notification:)),
                                       name: NSNotification.Name("Test123"),
                                       object: nil)

接收的方法改成有傳入值的方法。

@objc private func test(notification: NSNotification) {
    if let userInfoData = notification.userInfo?["QQ"] as? String {
      print(userInfoData)
    }
}

最後,發送通知的時候,改成以下的方法,多傳入userInfo即可。

///發送訊息,並且傳送資料
NotificationCenter.default.post(name: NSNotification.Name("Test123"),
                                object: nil,
                                userInfo: ["QQ":"QQ123"])
這樣就可以傳入資料了。
接著如果要移除觀察者的話,可以使用以下的語法

NotificationCenter.default.removeObserver(self)

///移除特定通知
NotificationCenter.default.removeObserver(self, name: NSNotification.Name("Test123"), object: nil)

這個算是一個滿方便的東西,但是要小心,Key必須小心管理,
不需要通知時,記得移除通知,避免發生意外。

沒有留言:

張貼留言