簡體   English   中英

下標:使用String枚舉訪問我的字典值

[英]Subscript: access my dictionary values with a String enumeration

我想做這樣的事情:使用String枚舉訪問我的字典值。 我試圖重載字典的下標,但沒有成功。

訪問字典:

let district = address[JsonKeys.district]

JsonKeys在哪里:

enum JsonKeys: String {
    case key1
    case key2
    case key...
}

我的下標重載如下:

extension Dictionary where Key: StringLiteralConvertible, Value: AnyObject {
    subscript(index: FOJsonKeys) -> AnyObject {
        get {
            return self[ index.rawValue] as! AnyObject
        }
    }
}

我收到以下消息:

**Cannot subscript a value of type 'Dictionary<Key, Value>' with an index of type 'String'**

我哪里錯了?

PS:不想這樣做(這可以糾正錯誤,但是這種方式無法讀取代碼):

let district = address[JsonKeys.district.rawValue]

該詞典是AlamoFire給我的Json解析詞典。 我很確定我不能更改其類型。

最簡單的方法是將字典放入更多上下文中。 在這種情況下,上下文是“它僅具有該枚舉的鍵”。 在Swift中解除類型非常簡單。 只需將其包裝在結構中即可。

// This could be a nested type inside JSONObject if you wanted.
enum JSONKeys: String {
    case district
}

// Here's my JSONObject. It's much more type-safe than the dictionary,
// and it's trivial to add methods to it.
struct JSONObject {
    let json: [String: AnyObject]
    init(_ json: [String: AnyObject]) {
        self.json = json
    }

    // You of course could make this generic if you wanted so that it
    // didn't have to be exactly JSONKeys. And of course you could add
    // a setter.
    subscript(key: JSONKeys) -> AnyObject? {
        return json[key.rawValue]
    }
}

let address: [String: AnyObject] = ["district": "Bob"]

// Now it's easy to lift our dictionary into a "JSONObject"
let json = JSONObject(address)

// And you don't even need to include the type. Just the key.
let district = json[.district]

嘗試這個:

extension Dictionary where Key: StringLiteralConvertible {
    subscript(index: JsonKeys) -> Value {
        get {
            return self[index.rawValue as! Key]!
        }
    }
}

請記住,在將約束作為Key: StringLiteralConvertible ,該擴展適用於其Key符合StringLiteralConvertible任何Dictionary。 (您知道String以外的許多其他類型都符合StringLiteralConvertible 。)

要調用下標self[] ,您需要傳遞Key類型的值。 index.rawValueString ,它不一定總是擴展中的Key

因此,我顯示的擴展名將對某些詞典有效,而對其他某些詞典會導致運行時崩潰。


類型安全的方法:

protocol MyJsonKeysConvertible {
    init(jsonKeys: JsonKeys)
}
extension String: MyJsonKeysConvertible {
    init(jsonKeys: JsonKeys) {self = jsonKeys.rawValue}
}
extension Dictionary where Key: MyJsonKeysConvertible {
    subscript(index: JsonKeys) -> Value {
        get {
            return self[Key(jsonKeys: index)]!
        }
    }
}

我知道這是一個老問題,但是我想我應該添加一個更易於擴展,重用和更輕量級的實現。

public protocol UsesRawValue {
    var rawValue: String { get }
}

extension JsonKeys: UsesRawValue {}

extension Dictionary where Key: ExpressibleByStringLiteral {
    public subscript(key: UsesRawValue) -> Value? {
        get { return self[key.rawValue as! Key] }
        set { self[key.rawValue as! Key] = newValue }
    }
}

根據這篇博客文章

這種方法只需要我們擴展字典一次,而不是擴展每個枚舉。 相反,每個枚舉都需要符合UsesRawValue 現在我們可以像這樣使用它。

ajson[JsonKeys.key1]
ajson[JsonKeys.key1] = "name"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM