具有typealias的协议不能符合AnyObject类型吗?

时间:2016-02-01 00:15:56

标签: swift nsuserdefaults swift-protocols

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

3 个答案:

答案 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)