Access to string values โ€‹โ€‹in an enumeration without using rawValue

I would like to replace my global string constants with a nested enumeration for the keys that I use to access the columns in the database.

The structure is as follows:

enum DatabaseKeys { enum User: String { case Table = "User" case Username = "username" ... } ... } 

Each table in the database is an internal enumeration, and the table name is an enumeration heading. The first case in each enumeration will be the name of the table, and the following cases will be the columns in its table.

To use this, it is quite simple:

 myUser[DatabaseKeys.User.Username.rawValue] = "Johnny" 

But I will use these listings a lot . There will be pain in adding .rawValue to each instance, and it is not as readable as we would like. How can I access a string value without using rawValue ? It would be great if I can do this:

 myUser[DatabaseKeys.User.Username] = "Johnny" 

Notice that I'm using Swift 2. If there is an even better way to do this, I'd love to hear it!

+8
string enums swift swift2
source share
4 answers

Until I found a way to do this using the desired enumeration syntax, this is possible with structs.

 struct DatabaseKeys { struct User { static let identifier = "User" static let Username = "username" } } 

For use:

 myUser[DatabaseKeys.User.Username] = "Johnny" 

In WatchKit templates, Apple uses such structures for storyboards and line type identifiers.

+14
source share

You can use the CustomStringConvertible protocol for this.

From the documentation,

String (instance) will work for an instance of any type, returning it if the instance is CustomStringConvertible. Using CustomStringConvertible as a general restriction or accessing the corresponding type description directly is therefore discouraged.

So, if you comply with this protocol and return your rawValue using the description method, you can use String (Table.User) to get the value.

 enum User: String, CustomStringConvertible { case Table = "User" case Username = "username" var description: String { return self.rawValue } } var myUser = [String: String]() myUser[String(DatabaseKeys.User.Username)] = "Johnny" print(myUser) // ["username": "Johnny"] 
+6
source share

If you can use User as a dictionary word instead of String ( User is Hashable by default), this will be the solution.

If not, you should use yours with nested structural and static variables / constants.

0
source share

You can do this with a special class:

 enum Names: String { case something, thing } class CustomData { subscript(key: Names) -> Any? { get { return self.customData[key.rawValue] } set(newValue) { self.customData[key.rawValue] = newValue } } private var customData = [String: Any]() } ... let cData = CustomData() cData[Names.thing] = 56 

Edit:
I found another solution that works with Swift 3:

 enum CustomKey: String { case one, two, three } extension Dictionary where Key: ExpressibleByStringLiteral { subscript(key: CustomKey) -> Value? { get { return self[key.rawValue as! Key] } set { self[key.rawValue as! Key] = newValue } } } var dict: [String: Any] = [:] dict[CustomKey.one] = 1 dict["two"] = true dict[.three] = 3 print(dict["one"]!) print(dict[CustomKey.two]!) print(dict[.three]!) 
0
source share

All Articles