I've been struggling with the new NSPasteboard APIs as well. The lack of sample 
code is appalling. I finally got file promises to work by incorporating some 
low level pasteboard manager calls. Note that NSPasteboard is not toll-free 
bridged with PasteboardRef, but you can go back & forth between the two worlds 
via the pasteboard name. Also note there is a warning on the console about no 
HFSPromises on the pasteboard, but the drag & drop works anyway. Hopefully all 
this will still work in the App Sandbox.

// ... write file URL promise to the pasteboard
ImageObjectPasteboardItem *item = [ImageObjectPasteboardItem 
itemWithImageObject:imageObject];
[item setDataProvider:self forTypes:[NSArray arrayWithObject:(NSString 
*)kPasteboardTypeFileURLPromise]];
[item setString:(NSString *)kUTTypeImage forType:(NSString 
*)kPasteboardTypeFilePromiseContent];
[pasteboard writeObjects:[NSArray arrayWithObject:item]];

// ... provide promised file URL
- (void)pasteboard:(NSPasteboard *)pasteboard item:(ImageObjectPasteboardItem 
*)item provideDataForType:(NSString *)type
{
        if ([type isEqualToString:(NSString *)kPasteboardTypeFileURLPromise]) {
                // get paste location from low level pasteboard
                PasteboardRef pboardRef = NULL;
                PasteboardCreate((__bridge CFStringRef)[pasteboard name], 
&pboardRef);
                if (pboardRef != NULL) {
                        PasteboardSynchronize(pboardRef);
                        CFURLRef urlRef = NULL;
                        PasteboardCopyPasteLocation(pboardRef, &urlRef);
                        if (urlRef != NULL) {
                                // create file at drop location
                                NSString *folderPath = [(__bridge NSURL 
*)urlRef path];
                                ImageObject *imageObject = [item imageObject];
                                NSString *path = [imageObject 
writeToFileInFolder:folderPath];
                                // set UTF-8 encoded file URL for promise data
                                NSURL *fileURL = [NSURL fileURLWithPath:path 
isDirectory:NO];
                                [item setString:[fileURL absoluteString] 
forType:(NSString *)kPasteboardTypeFileURLPromise];
                                // clean up
                                CFRelease(urlRef);
                        }
                        CFRelease(pboardRef);
                }
        }
}

// ... read file URL promise from the pasteboard
NSArray *items = [pasteboard readObjectsForClasses:[NSArray 
arrayWithObject:[NSPasteboardItem class]] options:nil];
for (NSPasteboardItem *item in items) {
        // we only want image files
        NSString *uti = [item stringForType:(NSString 
*)kPasteboardTypeFilePromiseContent];
        if (UTTypeConformsTo((__bridge CFStringRef)uti, kUTTypeImage)) {
                // set paste location via low level pasteboard
                PasteboardRef pboardRef = NULL;
                PasteboardCreate((__bridge CFStringRef)[pasteboard name], 
&pboardRef);
                if (pboardRef != NULL) {
                        PasteboardSynchronize(pboardRef);
                        PasteboardSetPasteLocation(pboardRef, (__bridge 
CFURLRef)[NSURL fileURLWithPath:m_addedGraphicsPath isDirectory:YES]);
                        // ask sender to create file at destination & return 
UTF-8 encoded URL
                        NSString *urlString = [item stringForType:(NSString 
*)kPasteboardTypeFileURLPromise];
                        if (urlString != nil) {
                                NSURL *fileURL = [NSURL 
URLWithString:urlString];
                                NSString *filePath = [fileURL path];
                                // ... do something with filePath
                        }
                        CFRelease(pboardRef);
                }
        }
}

On Aug 12, 2011, at 11:42 AM, Gabriele de Simone 
<subscri...@noiseindustries.com> wrote:

> Date: Fri, 12 Aug 2011 17:55:46 +0200
> From: Gabriele de Simone <subscri...@noiseindustries.com>
> Subject: NSPasteboardItem kPasteboardTypeFileURLPromise
> To: cocoa-dev@lists.apple.com
> Message-ID: <942f5e42-d2cf-4d8d-bc39-a1542606b...@noiseindustries.com>
> Content-Type: text/plain; charset=us-ascii
> 
> Hi everyone,
> 
> I am trying to implement "promise" type file drags from my app to the Finder 
> using the new, 10.6-and-later NSPasteboardItem APIs. I found almost no 
> information about it, and it didn't seem to make sense.
> 
> It starts in the outlineView:writeItems:toPasteboard: method of my 
> NSOutlineViewDataSource instance. In there, I allocate various 
> NSPasteboardItems for all files being dragged.
> 
> [...]
> 
>   NSArray * pasteboardTypes = [NSArray arrayWithObjects:
>       (NSString *)kPasteboardTypeFileURLPromise, 
>       (NSString *)kPasteboardTypeFilePromiseContent, nil];
>   NSMutableArray * pasteboardItems = [NSMutableArray array];
> 
>   for ( <however many files are selected> ) {
> 
>       NSPasteboardItem * pasteboardItem = [[[NSPasteboardItem alloc] init] 
> autorelease];
> 
>       [pasteboardItem setDataProvider:provider forTypes:pasteboardTypes];
>       [pasteboardItems addObject:pasteboardItem];
> 
>   }
> 
>   [pasteboard writeObjects:pasteboardItems];
> 
> [...]
> 
> As the drag moves away from my application and over the Desktop, the 
> "provider" instance used above is called once for each NSPasteboardItem, to 
> get the kPasteboardTypeFilePromiseContent. That part is (presumably) easy, 
> and my provider is returning the UTI for the promised file, based on its 
> contents. In the source code below, I have inserted kUTTypePNG to simplify:
> 
> - (void)pasteboard:(NSPasteboard *)pasteboard item:(NSPasteboardItem *)item 
> provideDataForType:(NSString *)type {
> 
>   if ( [type isEqualToString:(NSString *)kPasteboardTypeFilePromiseContent] ) 
> {
> 
>       [item setPropertyList:kUTTypePNG forType:type];
> 
>   } else if ( [type isEqualToString:(NSString 
> *)kPasteboardTypeFileURLPromise] ) {
> 
>       // What to do here?    
> 
>   }
> 
> }
> 
> The Finder seems happy with my UTI, and allows the drag to continue. The 
> problem is that if I drop the files onto the desktop, the 
> NSPasteboardDataProvider instance is called again, this time to get the 
> kPasteboardTypeFileURLPromise data. 
> 
> Intuitively, one would think that you have to:
> - Create the file that was promised, and keep the URL to that file handy.
> - Call one of the methods on NSPasteboardItem to supply the URL of the 
> promised file.
> - Allow the Finder to copy/move the files at will.
> 
> Unfortunately, there is no -[NSPasteboardItem setURL:forType:] method, no 
> -[NSURL writeToPasteboardItem:] method, or anything else that would seem to 
> "fit" this scenario.
> 
> What am I missing?
> 
> Thanks,
> Gabe

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to