I had similar requirements, except that I had a mesh of objects that I wanted to rebuild by dragging the selected objects to a new location. There are several ways to do this, including creating a custom object and implementing the NSPasteboardWriting and NSPasteboardReading protocols (and NSCoding protocols if you read data like NSPasteboardReadingAsKeyedArchive ), but this seems to be superfluous for dragging objects that remain internal to the application.
What I did was related to using NSPasteboardItem as a wrapper with a custom UTI type (it already implements NSPasteboardWriting and NSPasteboardReading ). First declare a custom UTI type:
#define kUTIMyCustomType @"com.mycompany.MyApp.MyCustomType"
This must be defined in the format "com.domain.MyApp", otherwise you will get errors of the form: "XXX is not a valid UTI string. It is not possible to set data for an invalid UTI". Apple mentions this in its documentation.
Then you must register this custom UTI type in the view in which the drag will be performed. This can be done at runtime and does not require any .plist add-ons. In your init method, you can add the following:
[self registerForDraggedTypes:[NSArray arrayWithObjects:(NSString *)kUTIMyCustomType, nil]];
Now make sure that a delegate is set for this view, and the delegate object implements the necessary methods of the NSDraggingSource and NSDraggingDestination . This will allow you to avoid violating the MVC design pattern by allowing the designated controller object to process the placement of data on cardboard, which is likely to include requesting model data (i.e., Indexes).
In particular, to place drag and drop indexes on objects that need to be moved when the drag starts as an NSPasteboardItem wrapper for your index data:
- (void) draggingSession:(NSDraggingSession *)session willBeginAtPoint:(NSPoint)screenPoint { NSPasteboard * pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; [pboard clearContents]; NSMutableArray * selectedIndexes = [NSMutableArray array];
And when the drag and drop operation is completed, read the data of the drag and drop index NSPasteboardItem :
- (BOOL) performDragOperation:(id <NSDraggingInfo>)sender { NSPasteboard * pasteboard = [sender draggingPasteboard]; // Check for custom NSPasteboardItem which wrap our custom object indexes. NSArray * classArray = [NSArray arrayWithObject:[NSPasteboardItem class]]; NSArray * items = [pasteboard readObjectsForClasses:classArray options:[NSDictionary dictionary]]; if (items == nil) return NO; // Convert array of NSPasteboardItem with NSString index reps. to array of NSNumber indexes. NSMutableArray * indexes = [NSMutableArray array]; for (NSPasteboardItem * item in items) [indexes addObject:[NSNumber numberWithInteger:[[item stringForType:kUTIMyCustomType] integerValue]]]; // // Handle dragged indexes… // return YES; }