我想用Dictionary
键(JSON字典)扩展String
,以允许使用enum
类型为RawValue
的任何String
下标。最终目标是使用多个enums
来对JSON字典进行下标。
enum JSONKey: String {
case one, two, three
}
enum OtherJSONKey: String {
case a, b, c
}
if let one = jsonDictionary[.one] { /* ... */ }
if let b = jsonDictionary[.b] { /* ... */ }
但是我不知道如何实现这一点。我知道我需要扩展
Dictionary
,但无法弄清楚通用扩展约束或方法扩展约束。我的第一个想法是尝试向下标方法添加通用约束。我不认为下标方法允许泛型。
extension Dictionary {
subscript<T: RawRepresentable>(key: T) -> Value? { /* ... */ }
}
即使将通用约束放在下标上可行,我仍然需要一种嵌套通用约束的方法。或将字典限制为基于字符串的枚举的键。要将其放入无效的代码中,我想这样做:
extension Dictionary where Key: RawRepresentable where RawValue == String {
subscript(key: Key) -> Value { /* ... */ }
}
// or
extension Dictionary {
subscript<T: RawRepresentable where RawValue == String>(key: T) -> Value { /* ... */ }
}
实际上可以扩展
Dictionary
以接受基于字符串的枚举作为下标吗?关于如何实现类似功能的其他想法包括
enum
继承以及为要用作下标的特定enums
创建协议(protocol)。我知道其中一些无法完成,但认为值得一提。因此,再次将其放入无效的代码中:enum JSONKey: String {}
enum NumbersJSONKey: JSONKey {
case one, two, three
}
enum LettersJSONKey: JSONKey {
case a, b, c
}
// or
protocol JSONKeys {}
enum NumbersJSONKey: JSONKey {
case one, two, three
}
enum LettersJSONKey: JSONKey {
case a, b, c
}
// then subscript with
if let one = json[.one] { /* ... */ }
更新:
我已经玩了更多,并且离得更近了。下面的扩展名可以编译,但是如果我实际尝试使用它,则会出现“下标不明确”的错误。
extension Collection where Iterator.Element == (key: String, value: AnyObject) {
// Compiles but can't be used because of ambiguous subscript.
subscript(key: CustomStringConvertible) -> AnyObject? {
guard let i = index(where: { $0.key == key.description }) else { return nil }
return self[i].value
}
}
@titaniumdecoy的答案有效,因此除非有人能提出更好的建议,否则它将被接受。
最佳答案
据我了解,您希望对任何具有String键的Dictionary进行扩展,以允许使用以String作为其RawValue类型的枚举来进行下标。如果是这样,以下内容将为您工作:
enum JSONKey: String {
case one, two, three
}
class JSONObject { }
extension Dictionary where Key: StringLiteralConvertible {
subscript(jsonKey: JSONKey) -> Value? {
get {
return self[jsonKey.rawValue as! Key]
}
set {
self[jsonKey.rawValue as! Key] = newValue
}
}
}
var jsonDict: [String: AnyObject] = [:]
jsonDict[JSONKey.one] = JSONObject()
jsonDict["two"] = JSONObject()
print(jsonDict["one"]!)
print(jsonDict[JSONKey.two]!)
如果要将其扩展为适用于String为RawValue类型的任何枚举,则需要泛型。由于Swift不支持通用下标(请参见SR-115),因此需要get/set方法或属性:
enum AnotherEnum: String {
case anotherCase
}
extension Dictionary where Key: StringLiteralConvertible {
func getValue<T: RawRepresentable where T.RawValue == String>(forKey key: T) -> Value? {
return self[key.rawValue as! Key]
}
mutating func setValue<T: RawRepresentable where T.RawValue == String>(value: Value, forKey key: T) {
self[key.rawValue as! Key] = value
}
}
jsonDict.setValue(JSONObject(), forKey: AnotherEnum.anotherCase)
print(jsonDict.getValue(forKey: AnotherEnum.anotherCase)!)
关于swift - Swift中带有基于字符串的枚举的下标字典,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38774772/