0

我正在尝试编写一种将数据存储到 NSUserDefaults 的通用方法。我遇到的问题是NSUserDefaults.standardUserDefaults().setValue(value, forKey: key)接受类型AnyObject?,如果我在协议中设置类型StringBool, 等不会映射到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()
}    
4

3 回答 3

0

如果您想让此代码在不进行太多更改的情况下工作,您可以只转换该值。

NSUserDefaults.standardUserDefaults().setValue(value as? AnyObject, forKey: key)

但是,我认为您需要在实现协议后验证该值以符合 AnyObject。

于 2016-02-01T00:54:47.373 回答
0

我认为您在这里滥用协议。您不希望给定类型的每个元素都具有相同的键,但这就是您实现它的方式。由于密钥是协议的一部分,并且您将密钥作为扩展的一部分附加,因此只能有一个密钥来存储字符串。这似乎不是很有用。(也许我在这里遗漏了用例;你能举例说明你打算如何使用它吗?)

您似乎要做的只是为NSUserDefaults. 那没问题。

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)

作为旁注,几乎没有理由调用synchronize(). NSUserDefaults这几乎完全是一个睡眠电话。它实际上并没有“同步”任何东西。

于 2016-02-01T00:55:06.953 回答
0

由于目的是尝试编写一种将数据存储到 NSUserDefaults 的通用方法。我假设你的意思是通用的。我建议尝试更直接的方法。只需将以下代码复制并粘贴到 Playground 即可查看结果。



    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)

于 2016-02-01T08:32:51.067 回答