NSTableView and drag and drop from Finder

一曲冷凌霜 提交于 2019-12-17 23:09:06

问题


I'm trying to implement drag and drop from the Finder into an NSTableView of my app. The setup uses an NSTableView, an array controller which acts as a datasource using Cocoa bindings to a Core Data store.

I did the following, basically following various blog posts I found on SO and other sites:

In the awakeFromNib of my view controller I call:

[[self sourcesTableView] registerForDraggedTypes:[NSArray arrayWithObjects: NSPasteboardTypePNG, nil]];

I subclassed NSArrayController and added the following methods to my subclass (the reasoning for subclassing is that the array controller needs to be informed of the drop as it acts as the datasource of the table view):

- (BOOL) tableView: (NSTableView *) aTableView acceptDrop: (id < NSDraggingInfo >) info row: (NSInteger) row dropOperation: (NSTableViewDropOperation)operation

My implementation for the above currently only writes to the log and then returns a boolean YES.

- (NSDragOperation) tableView: (NSTableView *) aTableView validateDrop: (id < NSDraggingInfo >) info proposedRow: (NSInteger) row proposedDropOperation: (NSTableViewDropOperation) operation

In IB I have the array controller pointing to my custom NSArrayController subclass.

Result: nothing. When I drag a PNG from the desktop onto my table view, nothing happens and the file happily bounces back to its origin. I must be doing something wrong but don't understand what. Where am I going wrong?


回答1:


A drag from the Finder is always a file drag, not an image drag. You'll need to support the dragging of URLs from the Finder.

To do that, you need to declare that you want URL types:

[[self sourcesTableView] registerForDraggedTypes:[NSArray arrayWithObject:(NSString*)kUTTypeFileURL]];

You can validate the files like so:

 - (NSDragOperation)tableView:(NSTableView *)aTableView validateDrop:(id < NSDraggingInfo >)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)operation
{
    //get the file URLs from the pasteboard
    NSPasteboard* pb = info.draggingPasteboard;

    //list the file type UTIs we want to accept
    NSArray* acceptedTypes = [NSArray arrayWithObject:(NSString*)kUTTypeImage];

    NSArray* urls = [pb readObjectsForClasses:[NSArray arrayWithObject:[NSURL class]]
     options:[NSDictionary dictionaryWithObjectsAndKeys:
                [NSNumber numberWithBool:YES],NSPasteboardURLReadingFileURLsOnlyKey,
                acceptedTypes, NSPasteboardURLReadingContentsConformToTypesKey,
                nil]];

    //only allow drag if there is exactly one file
    if(urls.count != 1)
        return NSDragOperationNone;

    return NSDragOperationCopy;
}

You'll then need to extract the URL again when the tableView:acceptDrop:row:dropOperation: method is called, create an image from the URL and then do something with that image.

Even though you are using Cocoa bindings, you still need to assign and implement an object as the datasource of your NSTableView if you want to use the dragging methods. Subclassing NSTableView will do no good because the datasource methods are not implemented in NSTableView.

You only need to implement the dragging-related methods in your datasource object, not the ones that provide table data as you're using bindings to do that. It's your responsibility to notify the array controller of the result of the drop, either by calling one of the NSArrayController methods such as insertObject:atArrangedObjectIndex: or by modifying the backing array using Key-Value Coding-compliant accessor methods.



来源:https://stackoverflow.com/questions/10308008/nstableview-and-drag-and-drop-from-finder

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!