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
How to Call Swiftui Navigationlink Conditionally
Create a Weak Container in Swift That Accepts a Native Swift Protocol
What the Difference of Keys and Values in Dictionary of Swift
How to Integrate Mapbox Sdk with Swiftui
Swift: How to Invalidate a Timer If the Timer Starts from a Function
How to Filter Nsarray in Swift
Datefromstring() Returns Incorrect Date
Convert Swift Encodable Class Typed as Any to Dictionary
Switch Statement for Imported Ns_Options (Rawoptionsettype) in Swift
Accessing Struct from One Class to Another
Swift Access Array with Index Gives Following Error. Any Idea Why
Rotation Gesture Produces Undesired Rotation
Swift Generics and Protocols Not Working on Uikit [Possible Bug]