In connection with my previous questions, I decided to subclass NSArrayController
in order to achieve the desired behavior.
class NSPresetArrayContr
The type of the value that you pass to encode(_:)
has to be a concrete type that implements Encodable
. This means you need to recover the object's real type from the Any
that you have. In order to cast, you must have a statically-specified type to which you are casting. You can't say object as! type(of: object)
, in other words; you have to say object as? MyClass
(or in a generic context you can say object as? T
).
Therefore, I believe that the only way to get around this is to statically enumerate the types you are working with, like so:
import Foundation
struct S : Encodable {
let i: Int
}
struct T : Encodable {
let f: Float
}
struct U : Encodable {
let b: Bool
}
func plistObject(from encodable: Any) -> Any? {
let encoded: Data?
switch encodable {
case let s as S:
encoded = try? PropertyListEncoder().encode(s)
case let t as T:
encoded = try? PropertyListEncoder().encode(t)
case let u as U:
encoded = try? PropertyListEncoder().encode(u)
default:
encoded = nil
}
guard let data = encoded else { return nil }
return try? PropertyListSerialization.propertyList(from: data,
options: [],
format: nil)
}
Needless to say, this is rather gross. It's inflexible, repetitive boilerplate. I'm not sure I can actually recommend its use. It's an answer to the literal question, not necessarily a solution to the problem.