0

When dropping images from the Photos app into my custom application, at - (void)dropInteraction:(UIDropInteraction *)interaction performDrop:(id<UIDropSession>)session I receive an NSURL* whose [url absoluteString] takes the following form:

file:///var/tmp/com.apple.DragUI.druid/.com.apple.DragUI.4tyFQQ/version=1&uuid=FF693BFB-99FF-4790-BBF2-A226593F718D&mode=compatible.png

Whenever I try to consume this file path, I receive a The file couldn’t be opened because there is no such file error. This makes sense, since the path itself doesn't look normal. I've seen other implementations that suggest it's possible that these should take a more expected path format.

Just in case the read issue was associated with access permissions, I can successfully wrap the operation with:

BOOL success = [url startAccessingSecurityScopedResource] /* begin */;

// ...

if (success) {
  [url stopAccessingSecurityScopedResource] /* terminate */;
}

However this doesn't impact on the response data. The application can currently also successfully read and write to the image gallery in other user journeys outside of Drag-and-Drop, so it doesn't appear to me to be related to missing permissions.

By contrast, I can handle NSConcreteData types that are passed from Brave Browser via performDrop without error.

Does anyone have an idea at what's happening? Is there any way that this provided URI can be normalized so that I can resolve the file correctly, or is it possibly indicative of an erroneous application state?

I'm running iOS 14 on a physical iPad.

1 Answer 1

0

Try parsing directly from the url instead of trying to load it from absoluteString, like so:

// given an NSURL object `url`
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];

Edit:

UIDropInteractionDelegate implementation I'm using

- (BOOL)dropInteraction:(UIDropInteraction *)interaction canHandleSession:(id<UIDropSession>)session {
    return [session canLoadObjectsOfClass:[UIImage class]];
}

- (UIDropProposal *)dropInteraction:(UIDropInteraction *)interaction sessionDidUpdate:(id<UIDropSession>)session {
    return [[UIDropProposal alloc] initWithDropOperation:UIDropOperationCopy];
}

- (void)dropInteraction:(UIDropInteraction *)interaction performDrop:(id<UIDropSession>)session {
    UIDragItem *item = session.items[0];
    NSArray *typeIdentifiers = item.itemProvider.registeredTypeIdentifiers;
    [item.itemProvider loadFileRepresentationForTypeIdentifier:typeIdentifiers[0]
                                             completionHandler:^(NSURL * _Nullable url,
                                                                 NSError * _Nullable error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSData *data = [NSData dataWithContentsOfURL:url];
            UIImage *image = [UIImage imageWithData:data];
            // use image...
        });
    }];
}
2
  • Hi, thanks very for your help. Unfortunately this didn't work; the call to dataWithContentsOfURL returns (null).
    – Mapsy
    Commented Nov 11, 2021 at 21:09
  • @Mapsy I updated my answer if you want to double check how you're implementing those delegate methods (tested dragging from Photos app) Commented Nov 13, 2021 at 19:29

Not the answer you're looking for? Browse other questions tagged or ask your own question.