Swift中Notification.Name這麼難用怎麼辦

沒故事的卓同學發表於2017-08-01

以前的傳送通知的引數就是一個簡單的字串:

NSNotificationCenter.defaultCenter().post("someStringThatShouldBeDeclared")複製程式碼

後來到了swift 3 中,改成了Notification.Name。定義在Notification的名稱空間下,是一個結構體,初始化函式接收一個字串。

extension NSNotification {
    public struct Name : RawRepresentable, Equatable, Hashable, Comparable {

        public init(_ rawValue: String)

        public init(rawValue: String)
    }
}複製程式碼

用起來就麻煩了一點:

NotificationCenter.default.post(Notification.Name(rawValue: "MyNotificationName"))複製程式碼

如果還是按照以前的方式定義一個全域性字串常量就沒有好好領會Swift精神了。

至少需要這樣,通過extension宣告一個靜態的常量:

extension Notification.Name {
    static let AccountBalanceUpdated = Notification.Name("accountBalanceUpdated")
}

// invocation
NotificationCenter.default.post(.AccountBalanceUpdated)複製程式碼

但是這種方式有一個小缺點,自定義的通知和系統的混在了一起,有時找起來比較尷尬。


這裡其實也有另外一個問題,這種方式不能避免通知的名字重複。雖然如果命名規範不會有這樣的問題,但是到底是個潛在的風險。

如果把上面兩個問題合起來看,就有了另外一種方式:利用Enum。
先宣告一個rawValue為字串的列舉。為了規避命名的衝突,宣告一個計算屬性,在每個值的rawValue前插入一個字串。再用這個字串去生成NSNotification.Name:

enum CPNotification: String {
    case userLogout
    case userLogin

    var stringValue: String {
        return "CP" + rawValue
    }

    var notificationName: NSNotification.Name {
        return NSNotification.Name(stringValue)
    }  
}複製程式碼

用起來就簡單了,自己寫一個擴充套件方法:

extension NotificationCenter {
    static func post(customeNotification name: CPNotification, object: Any? = nil){
        NotificationCenter.default.post(name: name.notificationName, object: object)
    }
}複製程式碼

這樣在使用時,直接點出來的就都是自定義的通知了。
當然在通知處理的地方也寫個擴充套件方法用起來就更爽了,比如我用Rx所以這樣寫:

extension Reactive where Base: NotificationCenter {

    func notification(custom name: CPNotification, object: AnyObject? = nil) -> Observable<Notification> {
       return notification(name.notificationName, object: object)
    }

}複製程式碼

用起來就是這樣:

       // 傳送通知
        NotificationCenter.post(customeNotification: .userLogout)

      // 接收通知
       let _ = NotificationCenter.default.rx.notification(custom: .userLogout).subscribe(onNext: { (value) in
            CPNetworkConfig.userID = nil
        })複製程式碼

歡迎在社交網路上關注我:

相關文章