虽然我个人鄙视 NSFileWrapper 的设计,但如果您只需要每个附件的数据,您可以通过 NSFileWrapper 的regularFileContents
方法将其作为 NSData 实例访问。但是,我需要为我的应用程序的附件提供一个有效且明确的路径名。要得到它比它应该做的工作要多得多:
您可以继承您的 NSTextView 并覆盖 NSDraggingDestination 协议方法draggingEntered:
,并且您可以在拖动操作期间遍历传递给您的应用程序的 NSPasteboardItem 对象。我选择将路径名及其 inode 编号保存在 NSMutableDictionary 中,因为 NSFileWrapper 可以为您提供引用文件的 inode。稍后,当我通过 NSAttributedString 访问 NSTextView 内容时,我可以使用 inode 作为索引来获取附件的路径名。
- (NSDragOperation)draggingEntered:(id < NSDraggingInfo >)sender {
// get pasteboard from dragging operation
NSPasteboard *pasteboard = [sender draggingPasteboard];
NSArray *pasteboardItems = [pasteboard pasteboardItems];
for ( NSPasteboardItem *pasteboardItem in pasteboardItems ) {
// look for a file url type from the pasteboard item
NSString *draggedURLString = [pasteboardItem stringForType:@"public.file-url"];
if (draggedURLString != nil) {
NSURL *draggedURL = [NSURL URLWithString:draggedURLString];
NSString *draggedPath = [draggedURL path];
NSLog(@"pathname: %@", draggedPath);
// do something with the path
// get file attributes
NSDictionary *draggedAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:draggedPath error:nil];
if ( draggedAttributes == nil)
continue;
// the NSFileWrapper allows access to the absolute file via NSFileSystemFileNumber
// put the path and the inode (returned as an NSNumber) into a NSMutableDictionary
NSNumber *draggedInode = [draggedAttributes objectForKey:NSFileSystemFileNumber];
[draggedFiles setObject:draggedPath forKey:draggedInode];
}
}
return [super draggingEntered:sender];
}
我的解决方案的一个问题,不影响我的应用程序,是多个文件(单个或一起)拖到视图中,这些文件是指向同一文件的硬链接,只会被索引为添加到字典中的最后一个路径名共享 inode。根据您的应用程序如何使用路径名,这可能是一个问题。