Skip to content

Drag and Drop Support

Joerg Jacobsen edited this page May 13, 2015 · 6 revisions

Drag&Drop Support in iMedia

A client app usually receives access to iMedia's browsable resources through Drag&Drop. When the user drags out a thumbnail from iMedia's object view iMedia will provide the following data to the pasteboard:

                    ┌───────────────────────────────────────────────────────────────────────────┐
                    │                                Pasteboard                                 │
                    ├───────────────────┬───────────────────┬───────────────────────────────────┤
                    │  kUTTypeFileURL   │  kUTTypeBookmark  │     kIMBObjectPasteboardType      │
┌───────────────────┼───────────────────┼───────────────────┼───────────────────────────────────┤
│Apple Media Library│  Security-scoped  │  Security-scoped  │          .location: nil           │
│  based resource   │        URL        │     bookmark      │  .locationBookmark: possibly nil  │
├───────────────────┼───────────────────┼───────────────────┼───────────────────────────────────┤
│Any other resource │Non-security-scoped│Non-security-scoped│      .location: possibly nil      │
│                   │        URL        │     bookmark      │  .locationBookmark: possibly nil  │
└───────────────────┴───────────────────┴───────────────────┴───────────────────────────────────┘

Note a few things:

  • if you access an IMBObject from the pasteboard its .location and .locationBookmark properties will probably still be nil. This is to give the client app better control over executing the costly operation of fetching a bookmark (think possibly a couple of thousand media objects being dragged).

  • Accessing .location if it is a file-based URL in a sandboxed environment is deprecated. This is because it is not security-scoped, so a sandboxed client app may not have access to its resource (in particular when it is using XPC services to access libraries). Instead, resort to .locationBookmark. Resolving it to a URL will give your app access to the denoted resource even if the bookmark is not security-scoped. We may even completely nil out this property for file-based URLs when detecting running in a sandboxed environment in a future version of iMedia.

    Note that the above mentioned equally applies to kUTTypeFileURL.

  • For any Apple Media Library based resource IMBObject.location will be nil. Derive the resource's URL from .locationBookmark. A location bookmark originating from Apple Media Library will be security-scoped if you configured the following:

      [IMBConfig setClientAppCanHandleSecurityScopedBookmarks:YES];
    

    Otherwise, the location bookmark will be non-security-scoped and possibly resulting in additional entitlement confirmation dialogs presented to the user (that is for any library she wants to access apart from the standard media resource paths)

  • In case of a Lightroom originating media object (IMBLightroomObject) .location and .locationBookmark do not refer to the same resource. Specifically:

    • IMBObject.location: URL denoting the master file of the Lightroom resource
    • IMBOject.locationBookmark: Bookmark resolving to a URL denoting a temporary file created by iMedia based on the so-called pyramid file representing the (possibly) user-edited derivative of the master file. The image-resolution of this temporary file is the same as the highest resolution the associated pyramid file offers.

    For better consistency we are currently evaluating to converge the semantics of these two properties so that IMBObject.location always refers to the same resource as IMBObject.locationBookmark refers to. This would imply creation of a new publicly available property IMBObject.masterLocation.

In summary, to get hold of the appropriate resource URL your code should look something like this:

if (!object.locationBookmark && (!object.location || [object.location isFileURL]))
{
    // As an alternative, you can use the asynchronous variant of -requestBookmarkWithError method
	// if you anticipate the user dragging thousands of resources at once
	// (requesting a bookmark does add some overhead) and if your completion block code is thread-safe:
    //            [object requestBookmarkWithQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0)
    //                             completionBlock:^(NSError *error) {
    //                                 // Your dragging code here
    //                             }];

    // Will have side-effect of setting bookmark on object
    if ([object requestBookmarkWithError:&error])
    {
        NSURL *URL = [object URLByResolvingBookmark];
        
        if (object.accessibility == kIMBResourceIsAccessibleSecurityScoped) [URL startAccessingSecurityScopedResource];
        
        // Do stuff with URL here...
        
        if (object.accessibility == kIMBResourceIsAccessibleSecurityScoped) [URL stopAccessingSecurityScopedResource];
        
    } else {
        lastError = error;
    }
} else if (object.location)
{
    // Coming here you will presumably load a resource from the internet (Facebook, Flickr and the like)
    
    // Do stuff with .location here...
}

For a definitive answer on what the current implementation of iMedia provides to the pasteboard it is always good to have a look at -[IMBObject pastboard:item:provideDataForType].

Clone this wiki locally