swift - Using an enum's default value as a dictionary key without explicitly casting to String -
if declare enum
this:
enum keys { case key_one case key_two }
i can print , automatically converted string
:
print(keys.key_one) // prints "key_one"
if make dictionary maps strings
whatever (but let's choose strings
again simplicity), think should able add key using keys.key_one
key, right? wrong.
var mydict = [string : string]() /// error: cannot subscript value of type '[string : string]' index /// of type 'keys' mydict[keys.key_one] = "firstkey"
i can if explicitly convert keys.key_one
string
though:
mydict[string(keys.key_one)] = "firstkey" print(mydict) // ["key_one": "firstkey"]
so want without having wrap enum
string()
every time.
i've tried few things doing extension
off of dictionary
using where
keyword key
, trying implement new subscript
functions, can't work. what's trick?
update solution
i found solution (see below).
i figured out extension solution wanted.
extension dictionary { subscript(key: keys) -> value? { { return self[string(key) as! key] } set(value) { guard let value = value else { self.removevalueforkey(string(key) as! key) return } self.updatevalue(value, forkey: string(key) as! key) } } } enum keys { case key_one case key_two } var mystringdict = [string : string]() /// adding first key value through string() way on purpose mystringdict.updatevalue("firstvalue", forkey: string(keys.key_one)) // mystringdict: ["key_one": "firstvalue"] // mystringdict[keys.key_one]!: firstvalue mystringdict[keys.key_two] = "secondvalue" // mystringdict: ["key_one": "firstvalue", "key_two": "secondvalue"] mystringdict[keys.key_one] = nil // mystringdict: ["key_two": "secondvalue"]
notice declared dictionary key type string
, i'm able use keys.key_one
, subscript in dictionary extension takes care of rest.
i can put better guarding around as!
conversion key
, i'm not sure it's needed, know enum can converted valid key
string()
cast.
improvement answer
even better, since i'm using api keys, made blank protocol called apikeys
, each model implement own keys
enum conforms apikeys
protocol. , dictionary's subscript updated take in apikeys
key
value.
extension dictionary { subscript(key: apikeys) -> value? { { return self[string(key) as! key] } set(value) { guard let value = value else { self.removevalueforkey(string(key) as! key) return } self.updatevalue(value, forkey: string(key) as! key) } } } protocol apikeys {} enum keys: apikeys { case key_one case key_two } enum model1keys: apikeys { case model_1_key_one case model_1_key_two } enum model2keys: apikeys { case model_2_key_one case model_2_key_two } var mystringdict = [string : string]() var model1stringdict = [string : string]() var model2stringdict = [string : string]() mystringdict.updatevalue("firstvalue", forkey: string(keys.key_one)) // mystringdict: ["key_one": "firstvalue"] mystringdict[keys.key_two] = "secondvalue" // mystringdict: ["key_one": "firstvalue", "key_two": "secondvalue"] mystringdict[keys.key_one] = nil // mystringdict: ["key_two": "secondvalue"] model1stringdict.updatevalue("firstvalue", forkey: string(model1keys.model_1_key_one)) // model1stringdict: ["model_1_key_one": "firstvalue"] model1stringdict[model1keys.model_1_key_two] = "secondvalue" // model1stringdict: ["model_1_key_one": "firstvalue", "model_1_key_two": "secondvalue"] model1stringdict[model1keys.model_1_key_one] = nil // model1stringdict: ["model_1_key_two": "secondvalue"] model2stringdict.updatevalue("firstvalue", forkey: string(model2keys.model_2_key_one)) // model2stringdict: ["model_2_key_one": "firstvalue"] model2stringdict[model2keys.model_2_key_two] = "secondvalue" // model2stringdict: ["model_2_key_one": "firstvalue", "model_2_key_two": "secondvalue"] model2stringdict[model2keys.model_2_key_one] = nil // model2stringdict: ["model_2_key_two": "secondvalue"]
Comments
Post a Comment