Let's break this down: NSApplication
and NSDocumentController
in NSDocument
based apps gives you -application:openFile:
or -openDocumentWithContentsOfURL:display:completionHandler:
for free in case of NSFilenamesPboardType
and NSURLPboardType
drops.
Note: I think under the hood this is implement with the NSAppleEventManager event handlers for kCoreEventClass
/kAEOpenDocuments
and kInternetEventClass
/kAEGetURL
.
Unfortunately they don't handle NSFilesPromisePboardType
.
Lets refresh our pasteboard knowledge: The pasteboard is shared amongst all application. There are default pasteboards for tasks like copy, find, and drag.
When the drag starts the application writes into the shared drag pasteboard. So all we need now is notification about the drop onto Dock icon.
This is where NSService
comes into play:
<key>NSServices</key>
<array>
<dict>
<key>NSMessage</key>
<string>openService</string>
<key>NSSendTypes</key>
<array>
<string>public.data</string>
</array>
<key>NSMenuItem</key>
<dict>
<key>default</key>
<string>Open</string>
</dict>
</dict>
</array>
And set it up in code:
- (void)applicationWillFinishLaunching:(NSNotification *)notification
{
[NSApp setServicesProvider:self];
}
- (void)openService:(NSPasteboard *)serviceBoard
userData:(NSString *)userData
error:(NSString **)error
{
}
One caveat is that the NSService
pasteboard is not the NSDragPboard
pasteboard.
But they are all shared, so we can just access the one we want:
NSPasteboard *dragPboard = [NSPasteboard pasteboardWithName:NSDragPboard];
if ([[dragPboard types] containsObject:NSFilesPromisePboardType])
{
}
The next problem is that we don't have -[NSDraggingInfo namesOfPromisedFilesDroppedAtDestination:]
.
#import <ApplicationServices/ApplicationServices.h>
Good old Carbon got us covered.
PasteboardRef pboardRef = NULL;
PasteboardCreate((__bridge CFStringRef)NSDragPboard, &pboardRef);
PasteboardSetPasteLocation(pboardRef, (__bridge CFURLRef)temporaryDirectory);
NSString *urlString = [dragPboard stringForType:(NSString *)kPasteboardTypeFileURLPromise];
CFRelease(pboardRef);
Handle like any other promise file from here on.