Swift 3通用扩展参数

Ben*_*ock 1 generics dictionary swift swift-extensions swift3

在Swift 2.x中,我有一个很好的小设置,允许我使用枚举成员存储和检索字典值:

public enum UserDefaultsKey : String {
    case mainWindowFrame
    case selectedTabIndex
    case recentSearches
}

extension Dictionary where Key : String {
    public subscript(key: UserDefaultsKey) -> Value? {
        get { return self[key.rawValue] }
        set { self[key.rawValue] = newValue }
    }
}
Run Code Online (Sandbox Code Playgroud)

这允许我访问这样的值:

let dict = userDefaults.dictionaryForKey("SearchPrefs")
if let recentSearches = dict?[.recentSearches] as? [String] {
    // Populate "Recent" menu items
}
Run Code Online (Sandbox Code Playgroud)

...而不是必须访问这样的值:

let dict = userDefaults.dictionaryForKey("SearchPrefs")
if let recentSearches = dict?[UserDefaultsKey.recentSearches.rawValue] as? [String] {
    // Populate "Recent" menu items
}
Run Code Online (Sandbox Code Playgroud)

注意:使用字符串文字来访问字典NSUserDefaults仅用于示例目的.我实际上不会忘记使用字典键的枚举,只是使用字符串文字来访问字典本身.:-)


无论如何,这对我的需求非常有用,它使阅读和维护代码NSUserDefaults更加愉快.

但是,自从将项目迁移到Swift 3后,我收到以下错误:

extension Dictionary where Key: String {
    public subscript(key: UserDefaultsKey) -> Value? { <---- Use of undeclared type 'Value'
                                              ~~~~~~
        get {
            return self[key.rawValue]
        }
        set {
            self[key.rawValue] = newValue
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我查看了生成的标头Dictionary,并且通用KeyValue参数仍然存在于结构的通用参数子句Dictionary,所以我不太清楚问题是什么.

我是否需要重写该where子句以符合我不知道的一些新的Swift 3语法?或者......可以不再访问扩展中的通用占位符类型吗?

我只是不知道该怎么办!

我的项目只有28个迁移错误需要解决.我真的很接近使用Swift 3,所以我喜欢任何指针(只要它们不是Unsafe和/或Raw).

谢谢!

Tim*_*len 6

目前,具体类型的通用参数不能约束为具体类型.这意味着像

extension Dictionary where Key == String
Run Code Online (Sandbox Code Playgroud)

不会编译.这是泛型系统的一个限制,希望它不会成为Swift 4中的问题.

虽然有一个解决方法,但它有点hacky:

protocol StringConvertible {
    init(_ string: String)
}

extension String: StringConvertible {}

extension Dictionary where Key: StringConvertible {

    subscript(key: UserDefaultsKey) -> Value? {
        get { return self[Key(key.rawValue)] }
        set { self[Key(key.rawValue)] = newValue }
    }

}
Run Code Online (Sandbox Code Playgroud)