0
votes

I would like to move items inside a NSCollectionView using its drag and drop delegate methods. I get it working until the item should get dropped. There is no destination indicator (gap) and when releasing the mouse the item is bouncing back. The delegates validateDrop and acceptDrop never gets called. The CollectionViewItems are showing data from custom objects:

enter image description here

func collectionView(_ collectionView: NSCollectionView, canDragItemsAt indexPaths: Set<IndexPath>, with event: NSEvent) -> Bool {

    print("canDragItem", indexPaths)
    return true
}

func collectionView(_ collectionView: NSCollectionView, writeItemsAt indexPaths: Set<IndexPath>, to pasteboard: NSPasteboard) -> Bool {

    let indexData = Data(NSKeyedArchiver.archivedData(withRootObject: indexPaths))
    pasteboard.declareTypes(["my_drag_type_id"], owner: self)
    pasteboard.setData(indexData, forType: "my_drag_type_id")

    print("write data", indexData)
    return true
}


func collectionView(_ collectionView: NSCollectionView, validateDrop draggingInfo: NSDraggingInfo, proposedIndex proposedDropIndex: UnsafeMutablePointer<Int>, dropOperation proposedDropOperation: UnsafeMutablePointer<NSCollectionViewDropOperation>) -> NSDragOperation {

    print("validation")
    return NSDragOperation.move
}

func collectionView(_ collectionView: NSCollectionView, acceptDrop draggingInfo: NSDraggingInfo, index: Int, dropOperation: NSCollectionViewDropOperation) -> Bool {

    let pb = NSPasteboard()
    let indexData = (pb.data(forType: "my_drag_type_id"))! as Data
    let indexPath = (NSKeyedUnarchiver.unarchiveObject(with: indexData)) as! IndexPath
    let draggedCell = indexPath.item as Int

    print("acceptDrop", draggedCell)


    return true
}

What the heck... I think there is something wrong with writing the item-data to be dragged in the pasteboard. Any suggestions.

1
Check the declarations of the methods. 'Path' is missing.Willeke
@Willeke thanks for the response but what do you mean? What path is missing where? Thanks!JFS
Your validateDrop and acceptDrop functions don't have correct parameters. The new versions have a proposedIndexPath and indexPath parameter.Willeke
Mhm, interesting. I took the methods right from XCode suggested when tipped in. I'll check that out.JFS
@Willeke In my case, that was the cause of the problem. Xcode autocomplete still suggests the old version, and it's still there in NSCollectionView.h, but no mention that it doesn't work any more. Could you submit that as an answer so that the question can be marked as answered?fbitterlich

1 Answers

1
votes

There are two possible causes of this issue. In this specific case Willeke's response is correct. You can in fact still use the old indexSet versions of all the drag-and-drop delegate functions, but if you do then you must make sure that all of them are the old versions, no mixing old and new!

In short, if your canDragItems: delegate function has a parameter called indexPaths, then ensure that writeItemsAt:, validateDrop: and acceptDrop: functions also make use of IndexPaths, not IndexSets.

Secondarily, and this was the case in my instance, check that you have remembered to register for the drag types you want your collection view to respond to somewhere sensible, i.e. viewDidLoad - see the code snippet below - and of course that the same drag type is being set in the pasteboard when generating the drag data in the first place!

collectionView.register(forDraggedTypes: [dragType])