Search code examples
objective-ccocoadrag-and-dropnsoutlineview

NSOutlineView drag-n-drop multiple items to single xml file Finder


I have a NSOutlineView with drag and drop support to reorder rows. Now I would like to add an export of the selected rows to a opml file in Finder. I've managed to set up NSFilePromiseProvider during outlineView:pasteboardWriterForItem:, which is called for every single row.

My current testing environment includes dummy methods of all related drag-n-drop delegate methods: NSDraggingSource, NSFilePromiseProviderDelegate, NSPasteboardItemDataProvider, NSPasteboardTypeOwner, NSPasteboardWriting, and the source and destination delegate methods of NSOutlineViewDataSource.
With a minimal method body and a print out whenever they are called.
And most of the time delegate methods are only called for specific NSPasteboardType like NSPasteboardTypeString.

How can I have one promised file for all selected rows at once? In the end I want to drag e.g., 3 rows from my outline view to the Desktop with 1 file created 'export.opml'.


Solution

  • Finally found a composition that works. Turns out outlineView:pasteboardWriterForItem: is not the right place to instantiate the NSFilePromiseProvider. Here is what worked for me:

    ThisClass <NSFilePromiseProviderDelegate>
    ...
    
    - (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pasteboard {
        NSFilePromiseProvider *prov = [[NSFilePromiseProvider alloc] initWithFileType:@"public.xml" delegate:self];
        [pasteboard writeObjects:@[prov]];
        return YES;
    }
    
    - (nonnull NSString *)filePromiseProvider:(nonnull NSFilePromiseProvider *)filePromiseProvider fileNameForType:(nonnull NSString *)fileType {
        return @"myfile.opml";
    }
    
    - (void)filePromiseProvider:(nonnull NSFilePromiseProvider *)filePromiseProvider writePromiseToURL:(nonnull NSURL *)url completionHandler:(nonnull void (^)(NSError * _Nullable))completionHandler {
        NSLog(@"%@ %@", url, filePromiseProvider.userInfo);
        // write to file ...
        completionHandler(nil);
    }