NSTableView 并从 Finder 拖放

Posted

技术标签:

【中文标题】NSTableView 并从 Finder 拖放【英文标题】:NSTableView and drag and drop from Finder 【发布时间】:2012-05-05 16:27:29 【问题描述】:

我正在尝试将 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 从桌面拖到我的表格视图上时,什么也没有发生,文件很高兴地弹回了它的原点。我一定做错了什么,但不明白是什么。我哪里错了?

【问题讨论】:

【参考方案1】:

从 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;

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

即使您使用的是 Cocoa 绑定,如果您想使用拖动方法,您仍然需要分配和实现一个对象作为您的 NSTableViewdatasource。子类化NSTableView 不会有好处,因为NSTableView 中没有实现数据源方法。

您只需要在您的数据源对象中实现与拖动相关的方法,而不是那些提供表格数据的方法,因为您使用绑定来执行此操作。您有责任通过调用 NSArrayController 方法之一(例如 insertObject:atArrangedObjectIndex:)或通过使用符合键值编码的访问器方法修改后备数组来通知数组控制器删除结果。

【讨论】:

谢谢,但表格视图仍然不接受任何拖放操作。我从 Finder 中拖动的任何文件都会反弹回来……我确实使用 Cocoa 绑定将表格附加到其数据源。 我已经更新了我的答案。您仍然需要实现一个数据源对象。

以上是关于NSTableView 并从 Finder 拖放的主要内容,如果未能解决你的问题,请参考以下文章

使用核心数据存储对 NSTableView 的拖放支持

在 NSTableView 中实现拖放

NSTableView 和 NSOutlineView 拖放

nstableview 拖放与自定义单元格视图

在拖放期间在 NSTableView 中打开一个间隙

拖出 NSTableView 以移除