ultimately, I was not able to make other parts of the solution work. It was something I found online to save a Homogenous Array, without stripping object type from the various object instances. Basically, even the donloadable 'finished' code... didn't compile, and it's way beyond me to try to figure it out. Although I did make an attempt and I feel like I gained some mildly deeper understanding of encoders/decoders... I don't feel that I have come away with a comprehensive understanding. I looked for a Codable 201 type coursework, would have helped. while lamenting this failed solution, which had me doing things that I was very uncomfortable doing, I hit on the main problem: there's no good way to interperet the incoming elements of an array in order to determine what class they are (indeed, that goes against the security needs answered by Codable and NSSecureCoding.)and it occurred to me that a wrapper class would work better, require less "acrobatic plumbing" in features of the language that are alien to me, and be fairly straight forward to setup. And the main thing about the wrapper class... it would allow me an opportunity to examine each object and figure out which class it is.the wrapper class has 2 properties :1. a 'type' property. an enum of Strings... just a set of keys really, that indicate class.2. a property of the same type as the array in question (in this case CNProperty)when it comes time to encode the array, you simply map the array to an array of wrapper objects. the wrapper, when it's object is set, automatically sets the type. and you encode that.when you decode the Wrapper array, the wrapper loads the type first. then it does a switch on the type, and loads the wrapped object as the appropriate type.it's another simple map to set the array from the wrapped objects.it's not trivial work, and I am not exactly happy that developers are sandbagged by security features in this way, but the new solution is fairly portable, easy to understand, and works without monkeying around in the guts of the language. It's a far cry from the solution I found online, and I feel like again... the next level of swift understanding has eluded me. But I'm the only person I know doing this, I'm self trained, and the Swift.org website is a place where people use opaque language, and throw around indescipherable buzzwords. One day, swift will stop being the wild west, and there will actually be human readable documents explaining all of this. meanwhile : my Object based solution:this is the object that I wrote that saves the array:the array is called 'props' take a look at the lines that encode and decode it. nothing fancy. but it works.public class CNProps : CNDagObj {
public var props: [CNProperty] = []
private enum CodingKeys: String, CodingKey {
case props
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(props.map({CNPropertyWrapper(prop: $0)}) , forKey: .props)
}
required public init(from decoder: Decoder) throws {
super.init()
let container = try decoder.container(keyedBy: CodingKeys.self)
let wrappers = try container.decode([CNPropertyWrapper].self, forKey: .props)
props = wrappers.map({ $0.prop })
}
public init(props: [CNProperty]) {
self.props = props
super.init()
}
public init(position: CGPoint, props: [CNProperty]) {
self.props = props
super.init(position: position)
}
}here's my wrapper class (i'm leaving out the various classes we are wrapping... it'l will just bog down the discussion CNProperty is the superClass, everything else is a subclass):the Choice to mirror the exact names of the classes in my enum, against the norms of lowercaing the first letter... That was made to help fight my dyslexia a bit. I might go back and change it, now that I know I've got the pattern worked out.public enum propType : String, Codable{
case CNProperty = "CNProperty"
case CNFloatProp = "CNFloatProp"
case CNStringProp = "CNStringProp"
case CNBoolProp = "CNBoolProp"
case CNIntProp = "CNIntProp"
case CNClampedFloatProp = "CNClampedFloatProp"
case CNColor_rgbaProp = "CNColor_rgbaProp"
case CNPoint_xyProp = "CNPoint_xyProp"
case CNSize_whProp = "CNSize_whProp"
case CNSize_whdProp = "CNSize_whdProp"
case CNVector_xyzProp = "CNVector_xyzProp"
}
class CNPropertyWrapper : Codable {
var type : propType = .CNProperty
var prop : CNProperty! = nil
private enum CodingKeys: String, CodingKey {
case prop
case type
}
init(prop: CNProperty) {
self.prop = prop
self.setType()
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(type, forKey: .type)
try container.encode(prop, forKey: .prop)
}
required public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
type = try container.decode(propType.self ,forKey: .type )
switch type{
case .CNProperty:
prop = try container.decode(CNProperty.self ,forKey: .prop )
case .CNFloatProp:
prop = try container.decode(CNFloatProp.self ,forKey: .prop )
case .CNStringProp:
prop = try container.decode(CNStringProp.self ,forKey: .prop )
case .CNBoolProp:
prop = try container.decode(CNBoolProp.self ,forKey: .prop )
case .CNIntProp:
prop = try container.decode(CNIntProp.self ,forKey: .prop )
case .CNClampedFloatProp:
prop = try container.decode(CNClampedFloatProp.self ,forKey: .prop )
case .CNColor_rgbaProp:
prop = try container.decode(CNColor_rgbaProp.self ,forKey: .prop )
case .CNPoint_xyProp:
prop = try container.decode(CNPoint_xyProp.self ,forKey: .prop )
case .CNSize_whProp:
prop = try container.decode(CNSize_whProp.self ,forKey: .prop )
case .CNSize_whdProp:
prop = try container.decode(CNSize_whdProp.self ,forKey: .prop )
case .CNVector_xyzProp:
prop = try container.decode(CNVector_xyzProp.self ,forKey: .prop )
}
}
func setType(){
switch self.prop{
case is CNFloatProp:
self.type = .CNFloatProp
case is CNStringProp:
self.type = .CNStringProp
case is CNBoolProp:
self.type = .CNBoolProp
case is CNIntProp:
self.type = .CNIntProp
case is CNClampedFloatProp:
self.type = .CNClampedFloatProp
case is CNColor_rgbaProp:
self.type = .CNColor_rgbaProp
case is CNPoint_xyProp:
if self.prop is CNVector_xyzProp{
self.type = .CNVector_xyzProp
}else{
self.type = .CNPoint_xyProp
}
case is CNSize_whProp:
if self.prop is CNSize_whdProp{
self.type = .CNSize_whdProp
}else{
self.type = .CNSize_whProp
}
default:
break
}
}
}