I'm fit to be tied, so I apologise for any harsh language.
I have an NSCoding compliant class hierarchy (mac os + swift)
And I am adding support for drag n drop.
This requires adding NSPasteboardReading/NSPasteboardWriting
which has been an abysmal experience. I got it working, but not correctly. Now I'm trying to do it right. And something that SHOULD just work, in the context of doing this work is failing to produce expected results. I've already spent too much time trying to guess what the ---- is going on.
upon completion of my drop, the source object is asked to provide a "propertyList." I used to encode my entire object and then in the init(withPasteboard) method I would copy the values from the instantiated resulting object to self. Which is a stupid and horrible way of doing the work, But at the time: after 2 weeks of literally trying random things with the pasteboard (lack of examples and documentation) was the only thing that worked.
Now, I am encoding the properties of the object, which includes 2 arrays of custom objects (which are both NSCoding compliant, and have been observed correctly encoding and decoding thousands of times.)
so it looks like this:
func pasteboardPropertyList(forType type: NSPasteboard.PasteboardType) -> Any? {
do {
let archiver = NSKeyedArchiver(requiringSecureCoding: false)
archiver.encode(name, forKey: "name")
archiver.encode(self.type, forKey: "type")
archiver.encode(children, forKey: "children")
// the problem is channels as follows:
archiver.encode(channels, forKey: "channels")
archiver.finishEncoding()
let data = archiver.encodedData
return data
} catch {
//debugPrint("archiveFailed for drag of node in toolbox")
}
return nil
}
required init?(pasteboardPropertyList propertyList: Any, ofType type: NSPasteboard.PasteboardType) {
super.init()
if let data = propertyList as? Data{
do {
//let newObject = try NSKeyedUnarchiver.unarchivedObject(ofClass: docDataObj.self, from: data)
let unarchiver = try NSKeyedUnarchiver.init(forReadingFrom: data)
self.name = unarchiver.decodeObject(forKey: "name" ) as! String
self.type = unarchiver.decodeObject(forKey: "type" ) as! String
if unarchiver.containsValue(forKey: "channels"){
let anObj = unarchiver.decodeObject(forKey: "channels" )
if anObj != nil{
if let objTest = anObj as? [docDataChannel]{
self.channels = objTest
}
}
}
if unarchiver.containsValue(forKey: "chidlren"){
self.children = unarchiver.decodeObject(forKey: "children" ) as! [docDataObj]
}
} catch {
//debugPrint("initing from property list failed trying to unarchive")
}
}
}
you'll notice a little cottage industry popping up around the property "channels"
That's where I always recieve a nil value from the unarchiver. I tried unarchiving every single type (Bool, Double, Float...) that unarchiver supports. There's nothing to unarchive for that key.
But I set it. With classes that easily archive elsewhere. I have followed the debugger, and the encode method is called on the contents of the channels array. As far as can be told, the objects are encoded.
AND the unarchiver reports that there is a value for that key. every single time. it returns true.
the children array... that's empty in my testing, but there IS a value for THAT key.
so the unarchiver swears it has a value that it doesn't, that I can confirm is set. what gives?