Example for Drag and Drop Inside Nscollectionview

NSCollectionView Drag Drop example

You have only implemented the delegate methods but there s no logic in some of the methods. For example to drag around a Collection Item I would add below logic :

-(BOOL)collectionView:(NSCollectionView *)collectionView writeItemsAtIndexes:(NSIndexSet *)indexes toPasteboard:(NSPasteboard *)pasteboard {
NSData *indexData = [NSKeyedArchiver archivedDataWithRootObject:indexes];
[pasteboard setDraggedTypes:@[@"my_drag_type_id"]];
[pasteboard setData:indexData forType:@"my_drag_type_id"];
// Here we temporarily store the index of the Cell,
// being dragged to pasteboard.
return YES;
}

- (BOOL)collectionView:(NSCollectionView *)collectionView acceptDrop:(id<NSDraggingInfo>)draggingInfo index:(NSInteger)index dropOperation:(NSCollectionViewDropOperation)dropOperation {
NSPasteboard *pBoard = [draggingInfo draggingPasteboard];
NSData *indexData = [pBoard dataForType:@"my_drag_type_id"];
NSIndexSet *indexes = [NSKeyedUnarchiver unarchiveObjectWithData:indexData];
NSInteger draggedCell = [indexes firstIndex];
// Now we know the Original Index (draggedCell) and the
// index of destination (index). Simply swap them in the collection view array.
return YES;
}

You also need to register the collection view to drag type in awakefromnib as

[_myCollectionView registerForDraggedTypes:@[@"my_drag_type_id"]];

And make sure that you have set the collection view as selectable.

NSPasteBoard for Drag and Drop

I haven't used the pasteboard with collection views, but I have with outline views. If you are just reordering internally dragged items you don't really need to use the paste functionality fully - it is designed to allow generic types to be passed around across apps.

You could just do the equivalent of this:

func outlineView(_ outlineView: NSOutlineView, pasteboardWriterForItem item: Any) -> NSPasteboardWriting? {
pasteboardItem.setString("Something to pass - not used", forType:MyConstants.pasteboardType)
return pasteboardItem
}

You'll need to have some way of internally caching the dragged items in the function above. Then, in the accept drop you can just check for your pasteboard type and use your cache.

Cannot get drag and drop to work onto NSCollectionView

From OS X 10.11 the NSCollectionViewDelegate methods take an index path instead of an index. For instance in

-(NSDragOperation)collectionView:(NSCollectionView *)collectionView validateDrop:(id<NSDraggingInfo>)draggingInfo proposedIndex:(NSInteger *)proposedDropIndex dropOperation:(NSCollectionViewDropOperation *)proposedDropOperation

the proposedIndex: parameter is replaced by proposedIndexPath:

- (NSDragOperation)collectionView:(NSCollectionView *)collectionView validateDrop:(id <NSDraggingInfo>)draggingInfo proposedIndexPath:(NSIndexPath * __nonnull * __nonnull)proposedDropIndexPath dropOperation:(NSCollectionViewDropOperation *)proposedDropOperation

NSCollectionView: Accept Drag Only Between Items, not Over

So, after some more research, I found that the validadeDrop method has
a parameter that describes exactly that, if the operation is over or in
between. And since it is given as a reference, one can change the
parameter to overwrite a certain behaviour. So, the solution is to add
this check to the method:

- (NSDragOperation)
collectionView:(NSCollectionView *)collectionView
validateDrop:(id<NSDraggingInfo>)draggingInfo
proposedIndex:(NSInteger *)proposedDropIndex
dropOperation:(NSCollectionViewDropOperation *)proposedDropOperation
{
/* ... */

if (*proposedDropOperation == NSCollectionViewDropOn)
*proposedDropOperation = NSCollectionViewDropBefore;

/* ... */
}


Related Topics



Leave a reply



Submit