【问题标题】:Codable Struct: Get Value by Key可编码结构:按键获取值
【发布时间】:2018-12-22 21:11:21
【问题描述】:

我有例如可编码结构User:

struct User: Codable {
    // ...
    var psnTag: String?
    var xblTag: String?
    var steamTag: String?
    var nintendoTag: String?
    var instagramId: String?
    // ...
}

stringKey 为String = "psnTag"

如何通过 stringKey 从实例中获取值?

像这样:

let stringKey = "psnTag"
user.hasKeyForPath(stringKey) //return Bool
user.valueForPath(stringKey) //return AnyObject

【问题讨论】:

  • 字符串键路径是 objective-c-ish 并且容易出错。如果 user.hasKeyForPath,您(开发人员)应该在 design 时知道。这是另一个相当昂贵的不必要的运行时检查。这是斯威夫特。 注意类型。使用原生 Swift Keypath 例如let keyPath = \User.psnTag
  • stackoverflow.com/a/46597941/2303865 如果您想在该帖子中添加扩展后为任何 Codable 结构实现这些方法extension Encodable { func hasKey(for path: String) -> Bool { return self[path] != nil } func value(for path: String) -> Any? { return self[path] } }

标签: swift key-value-coding


【解决方案1】:

从扩展Encodable 协议开始,为hasKeyvalue 声明方法

使用镜像

extension Encodable {
    func hasKey(for path: String) -> Bool {
        return Mirror(reflecting: self).children.contains { $0.label == path }
    }
    func value(for path: String) -> Any? {
        return Mirror(reflecting: self).children.first { $0.label == path }?.value
    }
}

使用 JSON 序列化

extension Encodable {
    func hasKey(for path: String) -> Bool {
        return dictionary?[path] != nil
    }
    func value(for path: String) -> Any? {
        return dictionary?[path]
    }    
    var dictionary: [String: Any]? {
        return (try? JSONSerialization.jsonObject(with: JSONEncoder().encode(self))) as? [String: Any]
    }
}

现在你可以像这样使用它了:

.hasKey(for: "key") //returns Bool
.value(for: "key") //returns Any?

【讨论】:

  • 你可以简单地扩展 Encodable
  • @LeoDabus 顺便说一句,一旦 OP 想要使用功能,我认为 subscript 不是好方法。但同样,我可能是错的。
  • 上一条评论有错别字extension Encodable { subscript(_ key: String) -> Any? { return (Mirror(reflecting: self).children.first { $0.label == key })?.value } }
  • 在生产代码中使用Mirror来实现字典转换似乎有点太复杂了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多