从 NSTableView 拖放到 Finder 的问题

Posted

技术标签:

【中文标题】从 NSTableView 拖放到 Finder 的问题【英文标题】:Problem with Drag-Drop from NSTableView to Finder 【发布时间】:2011-10-04 05:03:43 【问题描述】:

我创建了一个应用,它有一个代表一系列文件的 NSTableView。由此,我希望能够将一行(即文件名)从我的 NSTableView 拖到 Finder,并在该文件夹中创建文件。但是,我无法解决的一点是我需要修改原始文件的内容,然后才能将其复制到 Finder。

我添加了以下行,以便可以拖动到我的 NSTableView 之外:

[self.tableView setDraggingSourceOperationMask:NSDragOperationCopy forLocal:NO];    

如果我将当前文件位置添加到粘贴板,我可以让它复制实际文件,使用:

- (BOOL)tableView:(NSTableView *)aTableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard 
    [pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:nil];        
    NSMutableArray* dragfiles = [[NSMutableArray alloc] init];
    NSString* file = [self.files objectAtIndex:row];
    NSString* filepath = [[[self.pathControl URL] path] stringByAppendingPathComponent:file];
    [dragfiles addObject:filepath];
    [pboard setPropertyList:dragfiles forType: NSFilenamesPboardType];
    [dragfiles release];
 

但是,因为我想修改文件的内容,我不想把文件路径放到粘贴板上。我尝试过使用 NSFileWrapper,但 Finder 似乎不接受这是一种有效格式。

我检查了 Google,发现了一些建议,您可以创建一个临时文件并使用该文件路径。但是,这感觉很难看。

是否可以向 Finder 发送数据?有没有办法解决这个问题?

【问题讨论】:

【参考方案1】:

您很可能希望使用承诺文件,或NSFilesPromisePboardType 而不是NSFilenamesPboardType。 (注意:该文档所讨论的承诺文件方法 dragPromisedFilesOfTypes:fromRect:source:slideBack:event:namesOfPromisedFilesDroppedAtDestination: 是通用的 NSView 方法。NSTableView 定义了您将使用的更方便的方法,而不是通用的方法。也就是说,应该仍然提供有关承诺文件拖动如何工作的信息)。 NSTableView 使用 tableView:namesOfPromisedFilesDroppedAtDestination:forDraggedRowsWithIndexes:,您可以在其中处理文件。在您的tableView:writeRowsWithIndexes:toPasteboard: 方法中,您将声明NSFilesPromisePboardType,然后为您计划编写的文件类型设置文件扩展名数组。以下是概述了如何处理它的伪代码:

- (BOOL)tableView:(NSTableView *)aTableView
     writeRowsWithIndexes:(NSIndexSet *)rowIndexes
        toPasteboard:(NSPasteboard *)pboard 
     [pboard declareTypes:[NSArray arrayWithObjects:NSFilesPromisePboardType, nil]];

     NSMutableArray *filenameExtensions = [NSMutableArray array];
     NSArray *draggedFilenames = [self.files objectsAtIndexes:rowIndexes];
     for (NSString *filename in draggedFilenames) 
          NSString *filenameExtension = [filename pathExtension];
          if (filenameExtension.length) 
              [filenameExtensions addObject:filenameExtension];
          
     
     [pboard setPropertyList:filenameExtensions
                 forType:NSFilesPromisePboardType];
     return YES;

然后在你的 names-of-promisedFiles 方法中:

- (NSArray *)tableView:(NSTableView *)aTableView
       namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination
       forDraggedRowsWithIndexes:(NSIndexSet *)indexSet 

     NSArray *draggedFilenames = [self.files objectsAtIndexes:indexSet];

     for (NSString *filename in draggedFilenames) 
           // do your processing of files in here
          // if it may take a long time, you might need to do it on a background
          // thread

         NSString *fullPathToOriginal = nil;
          NSString *destPath =
         [[dropDestination path] stringByAppendingPathComponent:filename];


     
     return draggedFilenames;

您应该能够计算原始文件路径(不确定您是如何确定它的,所以我将它留在上面的代码中nil)和目标文件路径(使用上面代码中的类似内容)。

【讨论】:

太棒了。非常感谢。读完这篇文章后它工作了 5 分钟(昨晚花了 3 个小时试图让某些东西工作)。我的错误是错过了最初承诺的文件扩展名的相关性。再次感谢。【参考方案2】:

注意事项。

NSPasteboard.h 中有一条评论说:

/* Use of pboard types should be replaced with use of UTIs.  
   Pboard types will be deprecated in a future release. */

NSFilesPromisePboardType 定义之后说:

// Use (NSString *)kPasteboardTypeFileURLPromise

我只是花了几个小时把头撞在砖墙上,因为我在一些地方通过 (NSString *)kPasteboardTypeFileURLPromise 而不是 NSFilesPromisePboardType

看起来他们做的事情并不完全相同。我不知道为什么:

tableView:namesOfPromisedFilesDroppedAtDestination:forDraggedRowsWithIndexes 

没有被调用。当我切换回NSFilesPromisePboardType时, 突然它被调用了。

【讨论】:

NSFilesPromisePboardType 需要文件扩展名; kPasteboardTypeFileURLPromise 需要文件 URL; kPasteboardTypeFilePromiseContent(仅在 Pasteboard.h、AFAIK 中提到)需要 UTI。最后一个是第一个的现代替代品。 感谢您提供这些宝贵的提示,但您如何提供 kPasteboardTypeFileURLPromise 的 URL? NSURL 不是粘贴板类型。

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

Swift NSTableview 拖动选择多行而不是拖出表格

将文件拖放到 NSTableView 上?

从 finder 拖放到 WebView

拖出 NSTableView 以移除

如何在 Mac OS X 10.5 中处理从 Finder 中的多个文件拖放?

从Finder拖动后如何处理文件和文件夹结构[关闭]