不使用rawValue

时间:2015-08-30 16:52:52

标签: string swift enums swift2

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

结构如下:

enum DatabaseKeys {

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

    ...

}

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

要使用它,它非常简单:

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

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

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

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

5 个答案:

答案 0 :(得分:24)

虽然我没有找到使用enums所需语法的方法,但这可以使用结构。

struct DatabaseKeys {

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

}

使用:

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

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

答案 1 :(得分:11)

您可以使用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"]

答案 2 :(得分:2)

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

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

修改
我找到了另一个解决方案,使用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]!)

答案 3 :(得分:1)

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

enum KeychainKey: String {
   case userId
   case email
}

func callAsFunction() -> String {
    return self.rawValue
}

用法:

KeychainKey.userId()

答案 4 :(得分:0)

如果您能够使用User作为词典键而不是String(默认情况下UserHashable),那么这将是一个解决方案。

如果不是,你应该使用你的嵌套结构和静态变量/常量。