web-dev-qa-db-ja.com

rawValueを使用せずに列挙型の文字列値にアクセスする

グローバル文字列定数を、データベースの列にアクセスするために使用しているキーのネストされた列挙型に置き換えたいと思います。

構造は次のとおりです。

enum DatabaseKeys {

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

    ...

}

データベース内の各テーブルは内部列挙型であり、テーブルの名前が列挙型のタイトルです。各列挙型の最初のケースはテーブルの名前になり、次のケースはそのテーブルの列になります。

これを使用するには、非常に簡単です。

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

しかし、私はこれらの列挙型を使用しますたくさん。すべてのインスタンスに.rawValueを追加しなければならないのは面倒であり、私が望むほど読みやすくありません。 rawValueを使用せずに文字列値にアクセスするにはどうすればよいですか?私がこれを行うことができれば素晴らしいでしょう:

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

Swift 2.を使用していることに注意してください。これを達成するためのさらに良い方法があれば、ぜひ聞いてみてください。

19
Jordan H

列挙型で目的の構文を使用してこれを行う方法は見つかりませんでしたが、これは構造体を使用して可能です。

struct DatabaseKeys {

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

}

使用するには:

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

Appleは、WatchKitテンプレートのストーリーボードと行タイプの識別子にこのような構造体を使用しています。

26
Jordan H

これにはCustomStringConvertibleプロトコルを使用できます。

ドキュメントから、

String(instance)は任意のタイプのインスタンスで機能し、インスタンスがCustomStringConvertibleである場合はその説明を返します。したがって、CustomStringConvertibleをジェネリック制約として使用したり、適合タイプの説明に直接アクセスしたりすることはお勧めしません。

したがって、このプロトコルに準拠し、descriptionメソッドを介して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"]
11
Sandeep

カスタムクラスでこれを行うことができます:

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]!)
2
Ferenc Kiss

Userの代わりにStringを辞書キーとして使用できる場合(デフォルトではUserHashableです)、それが解決策になります。

そうでない場合は、ネストされた構造体と静的変数/定数を使用する必要があります。

0
Qbyte