NSTableView和从Finder中拖放

11

我正在尝试在我的应用程序的NSTableView中实现从Finder的拖放操作。此设置使用NSTableView,一个数组控制器作为数据源,使用Cocoa绑定到Core Data存储。

基本上,我按照在SO和其他网站上找到的各种博客文章进行了以下操作:

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

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

我子类化了NSArrayController,并将以下方法添加到我的子类中(子类化的原因是数组控制器需要被通知该拖动操作,因为它充当表格视图的数据源):

- (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个回答

21

从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中没有实现数据源方法。

您只需要在数据源对象中实现与拖放相关的方法,而不是提供表格数据的方法,因为您正在使用绑定来完成这些操作。您有责任通过调用诸如insertObject:atArrangedObjectIndex:之类的NSArrayController方法或使用符合Key-Value Coding的访问器方法修改后备数组,通知数组控制器拖放的结果。


谢谢,但是表格视图仍然无法接受任何拖放。我从Finder拖动的任何文件都会反弹回来... 我使用Cocoa绑定将表格连接到其数据源。 - Roger
我已经更新了我的答案。你仍然需要实现一个数据源对象。 - Rob Keniger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接