IKImageView with drag and drop
Q:
The IKImageView
has the ability to receive drags. How can I add the ability to perform outgoing drags? What flavor should I use to drag images to instances of IKImageView
?
A: IKImageView
provides drag and drop handlers for receiving images by way of the NSFilenamesPboardType
pasteboard flavor. They are able to receive drag and dropped image files, but they do not have a built in ability to provide outgoing drags. You can add that ability yourself by adding a -mouseDown
: (or -mouseMoved
:) handler to a subclass of IKImageView
that you can use to initiate outgoing drags.
The NSFilenamesPboardType
requires special handling because it must reference image files saved on disk and is not the same as just adding image data to the pasteboard. If you would like to provide drag and drop data to instances of IKImageView
in your own windows or in other application's windows, then you will need to implement your own outgoing drags using the NSFilenamesPboardType
flavor and manage the files yourself.
The listing below shows an example of how to initiate a drag from inside a -mouseDown
: handler on a subclass of IKImageView
that will allow you to drag images to other instances of IKImageView
.
Listing 1 Initiating an outgoing drag from an IKImageView
- (void)mouseDown:(NSEvent*)event |
{ |
NSLog(@"%s",__FUNCTION__); |
// if there is an image to drag around... |
if ( [self image] != NULL ) { |
// generate a file name, path, and url |
NSString *fileName = [NSString stringWithFormat:@"%@-%@", |
[[NSProcessInfo processInfo] globallyUniqueString], |
@"dragfile.png"]; |
NSString *filePath = |
[NSTemporaryDirectory() stringByAppendingPathComponent:fileName]; |
NSURL *fileURL = [NSURL fileURLWithPath:filePath]; |
// create a temporary file to house the image |
CGImageDestinationRef destination = CGImageDestinationCreateWithURL( |
(__bridge CFURLRef) fileURL, kUTTypePNG, 1, NULL); |
if ( destination != NULL ) { |
CGImageDestinationAddImage(destination, [self image], nil); |
if ( CGImageDestinationFinalize(destination) ) { |
// add a reference to the file path to the drag pasteboard |
// using the special NSFilenamesPboardType type |
NSPasteboard *dragPasteboard = |
[NSPasteboard pasteboardWithName:NSDragPboard]; |
[dragPasteboard declareTypes:@[NSFilenamesPboardType] owner:nil]; |
[dragPasteboard setPropertyList:@[filePath] |
forType:NSFilenamesPboardType]; |
// calculate the drag image and position |
NSImage* dragImage = [[NSWorkspace sharedWorkspace] |
iconForFile:filePath]; |
NSPoint dragPosition = [self convertPoint:[event locationInWindow] |
fromView:nil]; |
// perform the drag operation |
// this method call runs synchronously |
// so we can delete the file after it is |
// compete |
[self dragImage:dragImage |
at:dragPosition |
offset:NSZeroSize |
event:event |
pasteboard: dragPasteboard |
source:self |
slideBack:YES]; |
// the above dragImage method runs synchronously, so when we return |
// here the drag operation is technically complete, the receiver will |
// have been called, etc.... However, some receivers will only have |
// made note of the drag operation and they may not be finished |
// with the file just yet so it's important not to delete it right away. |
// In this sample we maintain the file on disk for a short time |
// before deleting it. |
const uint64_t kSecondsToKeepFile = 3, kNanosecondsPerSecond = 1000000000; |
dispatch_queue_t mainqueue = |
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); |
dispatch_time_t when = |
dispatch_time(0, kNanosecondsPerSecond*kSecondsToKeepFile); |
dispatch_after(when, mainqueue, |
^{ NSError *error; |
if (![[NSFileManager defaultManager] removeItemAtPath:filePath error:&error]) { |
NSLog(@"error removing %@ %@", filePath, error); |
} |
}); |
} |
// done with the image destination |
CFRelease(destination); |
} |
} |
} |
Document Revision History
Date | Notes |
---|---|
2014-08-05 | New document that explains how to use drag and drop with the IKImageView. |
Copyright © 2014 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2014-08-05