3

我正在编写一个带有基于视图的表格视图的 Mac 应用程序。这是一个图像列表,我希望用户能够将其拖到 Finder 以将每个图像保存到文件中。

数据源拥有一组自定义模型对象。模型对象都符合NSPasteboardWriting如下协议:

- (NSArray *)writableTypesForPasteboard:(NSPasteboard *)pasteboard {
    //self.screenshotImageDataType 在图像下载后设置,通过使用 CGImageSource 检查数据。
    //我已经验证了此时它是正确的。它在我的测试中的值是@"public.jpeg" (kUTTypeJPEG)。
    return @[ self.screenshotImageDataType, (__bridge NSString *)kUTTypeURL, (__bridge NSString *)kPasteboardTypeFilePromiseContent ];
}

- (id)pasteboardPropertyListForType:(NSString *)type {
    if (UTTypeEqual((__bridge CFStringRef)type, (__bridge CFStringRef)self.screenshotImageDataType)) {
        返回self.screenshotImageData;
    } else if (UTTypeEqual((__bridge CFStringRef)type, kUTTypeURL)) {
        返回 [self.screenshotImageURL pasteboardPropertyListForType:type];
    } else if (UTTypeEqual((__bridge CFStringRef)type, kPasteboardTypeFilePromiseContent)) {
        返回self.screenshotImageDataType;
    }

    id plist = [self.screenshotImage pasteboardPropertyListForType:type]
        ?: [self.screenshotImageURL pasteboardPropertyListForType:type];
    NSLog(@"plist for type %@: %@ %p", type, [plist className], plist);
    返回 [self.screenshotImage pasteboardPropertyListForType:type]
        ?: [self.screenshotImageURL pasteboardPropertyListForType:type];
}

我的对象拥有的 URL 是 Web URL,而不是本地文件。它们是下载图像的 URL。

table view 的 data-source-and-delegate-in-one 实现了一个与文件 promise 相关的方法:

- (NSArray *)tableView:(NSTableView *)tableView
namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestinationURL
forDraggedRowsWithIndexes:(NSIndexSet *)rows
{
    return [[self.screenshots objectsAtIndexes:rows] valueForKeyPath:@"screenshotImageURL.lastPathComponent"];
}

记录该表达式的值会生成具有正确文件扩展名的有效文件名。

最后,在 中windowDidLoad,我发送了一条消息,开启了整个混乱局面:

//Enable copy drags to non-local destinations (i.e., other apps).
[self.tableView setDraggingSourceOperationMask:NSDragOperationCopy forLocal:NO];

舞台搭建好了。窗帘拉上时会发生以下情况:

当我拖动到 Finder 拥有的窗口时,我拖动到的视图会突出显示,表明它将接受拖动。

但是,当我删除图像时,不会创建任何文件。

为什么我承诺的内容没有被创建?

4

1 回答 1

3

NSDraggingInfo协议namesOfPromisedFilesDroppedAtDestination:方法的文档给出了提示:

到此方法返回时,源可能已创建文件,也可能未创建文件。

显然,至少在表视图上下文中,这转化为“你自己创建文件,你这个懒惰的人”。

我修改了表格视图数据源的tableView:namesOfPromisedFilesDroppedAtDestination:forDraggedRowsWithIndexes:方法,告诉每个拖动的模型对象将自己写入文件(由目标目录 URL + 模型对象源 URL 中的文件名组成),并在模型对象类中实现了该功能。现在一切正常。

于 2012-10-12T04:13:55.680 回答