如何使用 NSFilePromiseProvider 写入粘贴板

How to write to the pasteboard with NSFilePromiseProvider

我正在尝试使用新的 NSPasteboardWriting API 支持 NSTableViewNSCollectionView 的多项目拖动。在我的真实应用程序中,我为我的 table 视图工作,但不为我的集合视图工作(永远不会调用 NSFilePromiseProviderDelegate 方法)。当我尝试从头开始构建演示应用程序时,我能够使用 NSTableView.

重现它

我在 DragDelegate 的两个方法中都设置了断点,但都没有被调用。不过,-tableView:pasteboardWriterForRow: 确实会被调用。当我拖出应用程序时,我看到该行的图像附加到光标,但就 Finder 而言,粘贴板上没有文件。没有选项可以拖放到 Dock 或 Finder window.

CollectionController 的一个实例被设置为我的 table 视图的 dataSource。它只有一个列,其文本标签绑定到表示的对象(因为它只是一个 NSString)。我是 Mojave 10.14.0 上的 运行 Xcode 10.0。这是我的类:

集合控制器

@interface CollectionController : NSObject <NSTableViewDataSource>

@property (strong) id<NSFilePromiseProviderDelegate> dragDelegate;

@end

@implementation CollectionController

- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
    return 1;
}

- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn
            row:(NSInteger)row
{
    return @"Test string";
}

- (id<NSPasteboardWriting>)tableView:(NSTableView *)tableView pasteboardWriterForRow:(NSInteger)row {
    self.dragDelegate = [[DragDelegate alloc] init];
    return [[NSFilePromiseProvider alloc] initWithFileType:@"public.text"
                                                  delegate:self.dragDelegate];

    return prov;
}

@end

拖动委托

@interface DragDelegate: NSObject <NSFilePromiseProviderDelegate>

@end

@implementation DragDelegate

- (NSString *)filePromiseProvider:(NSFilePromiseProvider *)filePromiseProvider
                  fileNameForType:(NSString *)fileType
{
    return @"file.txt";
}

- (void)filePromiseProvider:(NSFilePromiseProvider *)filePromiseProvider
          writePromiseToURL:(NSURL *)url
          completionHandler:(void (^)(NSError * _Nullable))completionHandler
{
    NSData *data = [@"test file contents" dataUsingEncoding:NSUTF8StringEncoding];
    [data writeToURL:url atomically:YES];
    completionHandler(nil);
}

@end

设置默认拖动操作

 - (void)setDraggingSourceOperationMask:(NSDragOperation)mask forLocal:(BOOL)isLocal;