11

我正在尝试将 Finder 拖放到我的应用程序的 NSTableView 中。该设置使用一个NSTableView数组控制器,它使用 Cocoa 绑定到 Core Data 存储充当数据源。

我做了以下事情,基本上是按照我在 SO 和其他网站上找到的各种博客文章:

awakeFromNib我的视图控制器中,我调用:

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

我对 NSArrayController 进行了子类化,并将以下方法添加到我的子类中(子类化的原因是数组控制器需要被告知 drop,因为它充当表视图的数据源):

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

我对上述内容的实现目前只写入日志,然后返回布尔值 YES。

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

在 IB 中,我的数组控制器指向我的自定义 NSArrayController 子类。

结果:什么都没有。当我将一个 PNG 从桌面拖到我的表格视图上时,什么也没有发生,文件很高兴地弹回了它的原点。我一定做错了什么,但不明白是什么。我哪里错了?

4

1 回答 1

20

Finder 中的拖动始终是文件拖动,而不是图像拖动。您需要支持从 Finder 中拖动 URL。

为此,您需要声明您需要 URL 类型:

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

您可以像这样验证文件:

 - (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;
}

然后,您需要在调用该方法时再次提取 URL tableView:acceptDrop:row:dropOperation:,从 URL 创建图像,然后对该图像执行某些操作。

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.

于 2012-04-25T04:57:03.390 回答