red when excited

NSTableView Drag and Drop with Bindings and NSArrayController

Tuesday, May 28, 2013

Red Sweater have an excellent blog post (link) providing an NSArrayController which provides support for drag and drop re-arrangement of NSTableView items. 


It works perfectly, but there is a gotcha… It is single minded in its purpose to provide the above capability, but it restricts your ability to provide drag and drop outside of the list as well, possibly in multiple formats. 

Sadly comments are closed on the blog so we weren’t able to post this minor tweak there, but here is an updated method for their class that will ensure any NSPasteboardWriting implementing class also writes its other formats onto the paste board during dragging (their class will just ignore these other types, its not interested, so the drag and drop still works). 
- (BOOL)tableView:(NSTableView *)tv writeRows:(NSArray*)rows toPasteboard:(NSPasteboard*)pboard{	
	if ([self draggingEnabled] == YES){
        
        //This is for the drag and drop within the table
        [pboard declareTypes:@[kRSRTVMovedRowsType] owner:self];
		[pboard setPropertyList:rows forType:kRSRTVMovedRowsType];

        //This adds all the other paste board types for anything the object supports itself
        for (NSNumber *row in rows){
            id arrangedObject = self.arrangedObjects[row.integerValue];
            if ([arrangedObject conformsToProtocol:@protocol(NSPasteboardWriting)]){
                NSObject *writableObject = arrangedObject;
                
                [pboard addTypes:[writableObject writableTypesForPasteboard:pboard] owner:writableObject];
                
                for (NSString *type in [writableObject writableTypesForPasteboard:pboard]){
                    id pasteBoardItem = [writableObject pasteboardPropertyListForType:type];
                    
                    if ([pasteBoardItem isKindOfClass:[NSString class]]){
                        [pboard setString:pasteBoardItem forType:type];
                    } else {
                        [pboard setPropertyList:pasteBoardItem forType:type];
                    }
                }
            }
        }
	}
	
    return [self draggingEnabled];
}
That’s all there is to it. Now all you need to do is add the NSPasteboardWriting protocol to any of the objects in your NSArrayController has and their additional types will be written too. 

Big thanks to Red Sweater for the original post, and hopefully others will find this useful.  
Please wait...