gpt4 book ai didi

swift - 将类型为 Any 的 Swift Encodable 类转换为字典

转载 作者:可可西里 更新时间:2023-11-01 01:07:34 28 4
gpt4 key购买 nike

关于 my previous questions ,我决定继承 NSArrayController 以实现所需的行为。

class NSPresetArrayController: NSArrayController {
override func addObject(_ object: Any) {
if let preset = object as? Preset {
super.addObject(["name": preset.name, "value": preset.value])
} else {
super.addObject(object)
}
}
}

这行得通,但是如果我想要一些适用于任何 Encodable 类的东西,而不仅仅是一个具有名为 namevalue 的两个属性的东西怎么办>?

基本上,问题是从类创建字典,其中键是属性名称,值是这些属性的值。

我试过这样写:

class NSPresetArrayController: NSArrayController {
override func addObject(_ object: Any) {
if let encodableObject = object as? Encodable {
let data = try! PropertyListEncoder().encode(encodableObject)
let any = try! PropertyListSerialization.propertyList(from: data, options: [], format: nil)

super.addObject(any)
}
}
}

但是,我得到一个编译错误:

Cannot invoke 'encode' with an argument list of type '(Encodable)'
1. Expected an argument list of type '(Value)'

我该如何解决这个问题才能编译?

最佳答案

问题是 protocols don't always conform to themselves . PropertyListEncoderencode(_:)方法需要一个 Value : Encodable 参数:

func encode<Value : Encodable>(_ value: Value) throws -> Data

然而 Encodable 类型本身目前无法满足此约束(但它可能会在该语言的 future 版本中满足)。

正如在链接的问答(和 also here)中探讨的那样,解决此限制的一种方法是打开 Encodable 值以挖掘底层具体类型,我们可以用它代替 Value。我们可以使用协议(protocol)扩展来做到这一点,并使用包装器类型来封装它:

extension Encodable {
fileprivate func openedEncode(to container: inout SingleValueEncodingContainer) throws {
try container.encode(self)
}
}

struct AnyEncodable : Encodable {
var value: Encodable
init(_ value: Encodable) {
self.value = value
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try value.openedEncode(to: &container)
}
}

应用于您的示例:

class NSPresetArrayController : NSArrayController {
override func addObject(_ object: Any) {
guard let object = object as? Encodable else {
// Not encodable, maybe do some error handling.
return
}
do {
let encoded = try PropertyListEncoder().encode(AnyEncodable(object))
let cocoaPropertyList = try PropertyListSerialization.propertyList(from: encoded, format: nil)
super.addObject(cocoaPropertyList)
} catch {
// Couldn't encode. Do some error handling.
}
}
}

关于swift - 将类型为 Any 的 Swift Encodable 类转换为字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54392379/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com