我试图编写一种将数据存储到NSUserDefaults的通用方法。我遇到的问题是NSUserDefaults.standardUserDefaults().setValue(value, forKey: key)
接收AnyObject?
类型,如果我在协议中设置了类型,String
,Bool
等,则不会#&} 39; t映射到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
Implemetation
/**
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()
}
答案 0 :(得分:0)
如果您希望在不改变太多的情况下使此代码正常工作,则只能转换该值。
NSUserDefaults.standardUserDefaults().setValue(value as? AnyObject, forKey: key)
但是,我认为您需要在实现协议后验证值以符合AnyObject。
答案 1 :(得分:0)
我认为你在这里滥用协议。您不希望给定类型的每个元素具有相同的密钥,但这是您实现它的方式。由于密钥是协议的一部分,并且您将密钥作为扩展的一部分附加,因此只能有一个密钥存储字符串。这似乎并不十分有用。 (也许我在这里错过了用例;你能举例说明你打算如何使用它吗?)
你似乎要做的就是为NSUserDefaults
创建一个更加Swifty的界面。这没问题。
struct UserDefaults {
static func setValue<T: AnyObject>(value: T, forKey key: String) {
NSUserDefaults.standardUserDefaults().setValue(value, forKey: key)
}
static func valueForKey<T>(key: String) -> T? {
return NSUserDefaults.standardUserDefaults().valueForKey(key) as? T
}
}
UserDefaults.setValue("123", forKey: "x")
let str: String? = UserDefaults.valueForKey("x")
print(str)
UserDefaults.setValue(123, forKey: "y")
let num: Int? = UserDefaults.valueForKey("y")
print(num)
作为附注,NSUserDefaults
上的there is almost never a reason to call synchronize()
。这几乎就是一个睡眠呼叫。它实际上没有&#34;同步&#34;任何东西。
答案 2 :(得分:0)
由于目的是尝试编写将数据存储到NSUserDefaults的一般方法。我假设你的意思是通用的。我建议尝试一些更简单的方法。只需复制&amp;将以下代码粘贴到游乐场以查看结果。
func getDefault(key: String) -> AnyObject? {
return NSUserDefaults.standardUserDefaults().valueForKey(key)
}
func setDefault(value: AnyObject?, forKey defaultName: String) {
NSUserDefaults.standardUserDefaults().setValue(value, forKey: defaultName)
}
func removeDefault(forKey defaultName: String) {
NSUserDefaults.standardUserDefaults().removeObjectForKey(defaultName)
}
//// String Example
let key1 = "Key1"
getDefault(key1)
setDefault("ABC", forKey: key1)
getDefault(key1)
removeDefault(forKey: key1)
getDefault(key1)
//// Number Example
let key2 = "Key2"
getDefault(key2)
setDefault(5678, forKey: key2)
getDefault(key2)
removeDefault(forKey: key2)
getDefault(key2)
//// NSDate Example
let key3 = "Key3"
getDefault(key3)
setDefault(NSDate(), forKey: key3)
getDefault(key3)
removeDefault(forKey: key3)
getDefault(key3)
//// Array Example
let key4 = "Key4"
getDefault(key4)
setDefault(["One", "Two", "Three", "Four"], forKey: key4)
getDefault(key4)
removeDefault(forKey: key4)
getDefault(key4)
//// Bool Example
let key5 = "Key5"
getDefault(key5)
setDefault(true, forKey: key5)
getDefault(key5)
removeDefault(forKey: key5)
getDefault(key5)
//// UserDefaultType
typealias UserDefaultType = String
let userDefaultType: UserDefaultType = "AnyStringHere"
let key6 = "Key6"
getDefault(key6)
setDefault(userDefaultType as AnyObject, forKey: key6)
getDefault(key6)
removeDefault(forKey: key6)
getDefault(key6)