Subscript Dictionary with String-based Enums in Swift

I want to expand Dictionarywith keys String(JSON dictionaries) to allow signatures with anyone enumthat has a type RawValue String. The final goal will be several enumsthat can be used to index JSON dictionaries.

enum JSONKey: String {
    case one, two, three
}

enum OtherJSONKey: String {
    case a, b, c
}

if let one = jsonDictionary[.one] { /* ... */ }
if let b = jsonDictionary[.b] { /* ... */ }

But I can’t figure out how to implement this. I know that I need to expand Dictionary, but cannot define general extension restrictions or method extension restrictions.

My first idea was to try to add a general constraint to the index method. I don't think substring methods allow generics to be used.

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, . , , , . , , :

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] { /* ... */ }

Update:

. , " ", .

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 , , - - .

+4
3

, , 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)!)
+6

Swift 4 Generic Subscripts :

extension Dictionary where Key: ExpressibleByStringLiteral {
    subscript<Index: RawRepresentable>(index: Index) -> Value? where Index.RawValue == String {
        get {
            return self[index.rawValue as! Key]
        }

        set {
            self[index.rawValue as! Key] = newValue
        }
    }
} 

Enum, String, RawValue type:

let value = jsonDict[JSONKey.one]

String Enum, JSONKey

+4

So this worked for me:

enum JSONKey: String {
    case one
    case two
    case three
}

extension Dictionary {
    subscript(key: JSONKey) -> Value {
        get {
            let k = key.rawValue as! Key
            return self[k]!
        }
        set {
            let k = key.rawValue as! Key
            self[k] = newValue
        }
    }

}

var jsonDictionary = [JSONKey.one.rawValue : "hello", JSONKey.two.rawValue : "hi there", JSONKey.three.rawValue : "foobar", "fourth value" : 4]

let one = jsonDictionary[.one]
let two = jsonDictionary[.two]
var three = jsonDictionary[.three]
let four = jsonDictionary["fourth value"]

jsonDictionary[.three] = 5
three = jsonDictionary[.three]

print("One: \(one), Two: \(two), Three: \(three), Four: \(four!)")

And he prints:

"One: hello, Two: hi there, Three: 5, Four: 4\n"
+3
source

Source: https://habr.com/ru/post/1650217/


All Articles