简体   繁体   中英

Example for Drag and Drop inside NSCollectionView

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:

在此处输入图片说明

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.

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, ie 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])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM