在不使用rawValue的情况下访问枚举中的字符串值

Jor*_*n H 19 string enums swift swift2

我想用我用于访问数据库中的列的键的嵌套枚举替换我的全局字符串常量.

结构如下:

enum DatabaseKeys {

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

    ...

}
Run Code Online (Sandbox Code Playgroud)

数据库中的每个表都是一个内部枚举,表的名称是枚举的标题.每个枚举中的第一个案例将是表的名称,以下案例是其表中的列.

要使用它,它非常简单:

myUser[DatabaseKeys.User.Username.rawValue] = "Johnny"
Run Code Online (Sandbox Code Playgroud)

但我会使用这些枚举了不少.必须附加.rawValue到每个实例将是一个痛苦,它不像我希望的那样可读.如何在不必使用的情况下访问String值rawValue?如果我能做到这一点,那就太好了:

myUser[DatabaseKeys.User.Username] = "Johnny"
Run Code Online (Sandbox Code Playgroud)

请注意,我正在使用Swift 2.如果有更好的方法来实现这一点,我很乐意听到它!

Jor*_*n H 27

虽然我没有找到使用枚举所需语法的方法,但可以使用结构.

struct DatabaseKeys {

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

}
Run Code Online (Sandbox Code Playgroud)

使用:

myUser[DatabaseKeys.User.Username] = "Johnny"
Run Code Online (Sandbox Code Playgroud)

Apple在WatchKit模板中使用这样的结构作为storyboard和行类型标识符.


San*_*eep 12

您可以使用CustomStringConvertible协议.

从文档,

String(instance)将适用于任何类型的实例,如果实例恰好是CustomStringConvertible,则返回其描述.因此,不鼓励使用CustomStringConvertible作为通用约束或直接访问符合类型的描述.

因此,如果您遵循此协议并通过描述方法返回rawValue,您将能够使用String(Table.User)来获取值.

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"]
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这很有趣.虽然必须使用`String`来初始化字符串同样效率低下.:P我实际上宁愿使用`rawValue`而不是将它包装在`String()`中. (8认同)

Lit*_*Dev 7

您可以在符合 String 的枚举上使用callAsFunction(Swift 5.2 中的新增功能)。

enum KeychainKey: String {
   case userId
   case email
}

func callAsFunction() -> String {
    return self.rawValue
}
Run Code Online (Sandbox Code Playgroud)

用法:

KeychainKey.userId()
Run Code Online (Sandbox Code Playgroud)


Fer*_*iss 5

您可以使用自定义类来执行此操作:

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
Run Code Online (Sandbox Code Playgroud)

编辑:
我找到了另一个解决方案,与 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]!)
Run Code Online (Sandbox Code Playgroud)