Dov
Dov

Reputation: 16186

How to write to the pasteboard with NSFilePromiseProvider

I'm trying to support multi-item dragging with NSTableView and NSCollectionView using the new NSPasteboardWriting APIs. In my real app, I have dragging working for my table view, but not for my collection view (the NSFilePromiseProviderDelegate methods never get called). When I tried building a demo app from the ground up, I was able to reproduce this with an NSTableView.

I've set breakpoints inside both methods of DragDelegate, and neither gets called. -tableView:pasteboardWriterForRow: does get called, though. When I drag outside the app, I see the row's image attached to the cursor, but as far as Finder is concerned, there are no files on the pasteboard. There's no option to drop onto the Dock or a Finder window.

An instance of CollectionController is set as my table view's dataSource. It has a single column, whose text label is bound to the represented object (since it's just an NSString). I'm running Xcode 10.0 on Mojave 10.14.0. Here are the classes I have:

CollectionController

@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

DragDelegate

@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

Upvotes: 2

Views: 948

Answers (1)

Willeke
Willeke

Reputation: 15623

Set the default dragging operation with

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

Upvotes: 2

Related Questions