我正在尝试编写一种将数据存储到 NSUserDefaults 的通用方法。我遇到的问题是NSUserDefaults.standardUserDefaults().setValue(value, forKey: key)
接受类型AnyObject?
,如果我在协议中设置类型String
,Bool
, 等不会映射到AnyObject?
,因为它们不是对象。无论如何,我怎样才能使这段代码工作而不必为每种类型实现扩展?感谢帮助!
protocol UserDefaultUtility {
typealias UserDefaultType
var key: String { get }
func getDefault() -> UserDefaultType?
func setDefault(value: UserDefaultType?)
func removeDefault()
}
extension UserDefaultUtility {
func getDefault() -> UserDefaultType? {
return NSUserDefaults.standardUserDefaults().valueForKey(key) as? UserDefaultType
}
// Doesn't work-- Cannot convert value of type 'Self.UserDefaultType' to expected argument type 'AnyObject?'
/*
func setDefault(value: UserDefaultType) {
NSUserDefaults.standardUserDefaults().setValue(value, forKey: key)
NSUserDefaults.standardUserDefaults().synchronize()
}
*/
func removeDefault() {
NSUserDefaults.standardUserDefaults().removeObjectForKey(key)
NSUserDefaults.standardUserDefaults().synchronize()
}
}
// I have to do this instead to get it to work for any type I want to save to user defaults
extension UserDefaultUtility where UserDefaultType == String {
func setDefault(value: String?) {
NSUserDefaults.standardUserDefaults().setValue(value, forKey: key)
NSUserDefaults.standardUserDefaults().synchronize()
}
}
编辑 1
实施
/**
Strings stored in UserDefaults are accessed by this utility. Note that the String in the enum header is there to tell the enum that it's raw value is a String.
*/
enum StringUserDefaulstUtility: String, UserDefaultsUtility {
typealias UserDefaultType = String
case UserFirstName = "userFirstName"
case UserLastName = "userLastName"
var key: String {
get {
return self.rawValue
}
}
}
enum NSDateUserDefaultsUtility: String, UserDefaultsUtility {
typealias UserDefaultType = NSDate
case TokenExpiration = "tokenExpiration"
var key: String {
get {
return self.rawValue
}
}
}
用例
func someUselessFunc() {
// Sets the user's first name
StringUserDefaulstUtility.UserFirstName.setDefault("Matt")
// Gets the user's first name
StringUserDefaulstUtility.UserFirstName.getDefault()
// Removes the user's first name
StringUserDefaulstUtility.UserFirstName.removeDefault()
}