在Swift 3之前,我們需要使用字串去作為發送或監聽NotificationCenter的事件名稱,而從Swift 3之後,我們可以使用Notification.Name來作為NotificationCenter的名稱。

使用這方法我們就可以事先定義好,不用擔心在不同的地方打錯字串而造成事件無法收到的問題,只需要先像這樣宣告好Name: extension NSNotification.Name { static var userLogin = NSNotification.Name(rawValue: "UserLogin") }

之後就可以用這個Name去處理NotificationCenter的事件 // 發送 NotificationCenter.default.post(name: .userLogin, object: user)``// 監聽 NotificationCenter.default.addObserver(forName: .userLogin, object: nil, queue: nil) {(notification) in // Handle }

這方法的好處是,在name的位置我們只需要打 . Xcode就會跳出所有定義好的Name,從而避免字串打錯字而發生行為錯誤的問題。

那這引起我的另一個想法,我們是否可以用類似的方法去處理UserDefaults或Keychain等等的Keys呢?

嘗試之後,發現可以用一個extension就做到類似的行為,以下以UserDefaults為例

首先貼上以下這段 extension UserDefaults { enum Key { case default(key: String) init(key: String) { self = .default(key: key) } } }

這裡我們使用extension去建立一個enum在UserDefaults下面,並放一個default的case去儲存字串

然後用extension給UserDefaults新增一些使用UserDefaults.Key而非String的方法: `extension UserDefaults {
func set(_ value: Any?, forKey key: UserDefaults.Key) {
if case UserDefaults.Key.default(let k) = key {
self.set(value, forKey: k)
}
}

func removeObject(forKey key: UserDefaults.Key) {  
    if case UserDefaults.Key.default(let k) = key {  
        self.removeObject(forKey: k)  
    }  
}  

func value(forKey key: UserDefaults.Key) -> Any? {  
    if case UserDefaults.Key.default(let k) = key {  
        return self.value(forKey: k)  
    }  
    return nil  
}  

func string(forKey key: UserDefaults.Key) -> String? {  
    if case UserDefaults.Key.default(let k) = key {  
        return self.string(forKey: k)  
    }  
    return nil  
}  

func dictionary(forKey key: UserDefaults.Key) -> Dictionary<String, Any>? {  
    if case UserDefaults.Key.default(let k) = key {  
        return self.dictionary(forKey: k)  
    }  
    return nil  
}  

func integer(forKey key: UserDefaults.Key) -> Int {  
    if case UserDefaults.Key.default(let k) = key {  
        return self.integer(forKey: k)  
    }  
    return 0  
}  

func float(forKey key: UserDefaults.Key) -> Float {  
    if case UserDefaults.Key.default(let k) = key {  
        return self.float(forKey: k)  
    }  
    return 0.0  
}  

func double(forKey key: UserDefaults.Key) -> Double {  
    if case UserDefaults.Key.default(let k) = key {  
        return self.double(forKey: k)  
    }  
    return 0.0  
}  

func bool(forKey key: UserDefaults.Key) -> Bool {  
    if case UserDefaults.Key.default(let k) = key {  
        return self.bool(forKey: k)  
    }  
    return false  
}  

}`

最後再如同Notification.Name那般,建立UserDefaults.Key extension UserDefaults.Key { static var user = UserDefaults.Key(key: "User") static var token = UserDefaults.Key(key: "Token") }

這樣之後我們就可以用下面這種方法去設定、刪除或取得UserDefaults中的值了 UserDefaults.standard.set(userData, forKey: .user)``UserDefaults.standard.removeObject(forKey: .user)``let userData = userDefaults.dictionary(forKey: .user)

相同的方法也可以用在其他需要輸入字串當Key的方法上,這樣將可以避免打錯字的問題,也可以直接看到所有目前存在著的Key,並使用Auto Completion