关于mypreviousquestions,我决定将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
类都有效的东西,而不仅仅是一个具有两个名为name
和value
属性的东西呢?基本上,问题在于从类中创建字典,其中键是属性名,值是这些属性的值。
我试着这样写:
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。PropertyListEncoder
的encode(_:)
方法需要一个Value : Encodable
参数:
func encode<Value : Encodable>(_ value: Value) throws -> Data
但是,
Encodable
类型本身当前无法满足此约束(但在语言的未来版本中可能会很好地满足)。正如链接问答(和also here中所探讨的那样,解决这一限制的一种方法是打开
Encodable
值,以便挖掘出底层的混凝土类型,我们可以将其替换为Value
。我们可以通过协议扩展来实现这一点,并使用包装类型来封装它: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/