drag n drop : a brick wall.

I'm at a stand still and I need guidance.


I am trying to implement drag and drop in a MAC OS X app, using NSPasteboardWriting, NSPasteboardReading, NSPasteboardItemProvider.

it's not working, but it's not crashing. It's just not working.


I have tons of code in this. It's actually very alarming just how much leg workhas to be done in order to enable drag n drop, but as far as I am able to tell... I should be getting something. a crash. a malformed object. an error message. Nope.


I've tried to make a compact copy of all of the pertinent code:

// in the NSDraggingSource which is also the NSPasteboardItemProvider:

// this is the function that ultimately handles mouseDown in a delegate:
open override func mouseDown(event : NSEvent, view: NSView, forProp: BKControlProps)->Bool{
    
    if let aNode = forProp.representedObject as? docDataObj{
        pasteboardNode = aNode
    }
    
    let pasteboardItem = NSPasteboardItem()
    pasteboardItem.setDataProvider(self, forTypes: [NSPasteboard.PasteboardType(rawValue: "com.bktools.node")])
    let dragImg = NSImage.init(byReferencing: Bundle.main.urlForImageResource("dragImg")!)
    let draggingItem = NSDraggingItem(pasteboardWriter: pasteboardItem)
    let winLoc = event.locationInWindow
    draggingItem.setDraggingFrame(CGRect(x: winLoc.x - 25, y: winLoc.y - 25, width: 50, height: 50), contents:dragImg)
    view.beginDraggingSession(with: [draggingItem], event: event, source: self as! NSDraggingSource)
    
    return true
}

// this is the pasteboardItem provider stuff:
// the delegate is a to-many delegate, so we needed a way to temporarily store the item being dragged.you can see that we set that in the mousedown
var pasteboardNode : docDataObj? = nil
func pasteboard(_ pasteboard: NSPasteboard?, item: NSPasteboardItem, provideDataForType type: NSPasteboard.PasteboardType) {
    if let realItem = pasteboardNode{
        pasteboard?.writeObjects([realItem])
    }
}


// now on to the actual object that is transported, which is NSPasteboardReading, and Wiriting, it is also NSCoding compliant.

// note: this method makes no sense to me. we get data passed, which contains a complete copy of an object, but by the time we get it, we already have an instance of that object type.
// but it doesn't yet matter: this method is never called. haven't even come close to testing it.
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)
            if let anItem = newObject{
                self.name = anItem.name
                self.type = anItem.type
                self.channels = anItem.channels
                self.children = anItem.children
            }
        } catch  {
            debugPrint("initing from property list failed trying to unarchive")
        }
}

    static func readableTypes(for pasteboard: NSPasteboard) -> [NSPasteboard.PasteboardType] {
        return [NSPasteboard.PasteboardType(rawValue: "com.bktools.node")]
}

    
    
func pasteboardPropertyList(forType type: NSPasteboard.PasteboardType) -> Any? {
    var data : Data? = nil
    do {
        data = try NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: false)
        
    } catch  {
        debugPrint("archiveFailed for drag of node in toolbox")
    }
    return data
}
    
    
    
    
func writableTypes(for pasteboard: NSPasteboard) -> [NSPasteboard.PasteboardType] {
    return [NSPasteboard.PasteboardType(rawValue: "com.bktools.node")]
}
    
    

// now at the dragging destination:

// handling drops.
open override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation{
    debugPrint("drag enter")
    return [.copy, .move]
}
open override func draggingUpdated(_ sender: NSDraggingInfo) -> NSDragOperation{
    debugPrint("drag updated")
    return [.copy, .move]
}
open override func draggingExited(_ sender: NSDraggingInfo?){
    debugPrint("drag exited")
    // don't do anything... or... update the ui in some way.
}
open override func prepareForDragOperation(_ sender: NSDraggingInfo) -> Bool{
    debugPrint("prepare for drop")
    return true
}
    
    
    
open override func performDragOperation(_ sender: NSDraggingInfo) -> Bool{
    debugPrint("accepting drop")

    let pasteBoard = sender.draggingPasteboard
    // we are doing some veracity testing below here:
    let types = pasteBoard.types
    // types returns 'com.bktools.node' in an array.
    let item = pasteBoard.canReadObject( forClasses: [docDataObj.self], options:nil)
    // item returns true.
    
    // here is the problem. when this code is executed : nodes returns as an empty array.
    // the docDataObj being transported is actually archived, turned into Data, and sent to the pasteboard.
    // the pastebord shows that it has 1 item... and that it is the correct type This method does not return a nil value. i returns an empty array.
    // and at no point, is a docDataObj instantiated from a propertyList.
    if let nodes = pasteBoard.readObjects(forClasses: [docDataObj.self], options:nil) as? [docDataObj]{
        self.appData?.docData += nodes
        return true
    }
    
    return true
}
    
    
open override func concludeDragOperation(_ sender: NSDraggingInfo?){
    debugPrint("drop completed")
}