1

With file access in a sandboxed osx app with swift in mind, does it work the same with URLs provided via Finder or other apps drops?

As there's no NSOpenPanel call to afford folder access as in this example, just urls - I think the folder access is implicit since the user dragged the file from the source / desktop "folder" much the same as implicit selection via the open dialog.

I have not begun the sandbox migration yet but wanted to verify my thinking was accurate, but here's a candidate routine that does not work in sandbox mode:

func performDragOperation(_ sender: NSDraggingInfo!) -> Bool {
    let pboard = sender.draggingPasteboard()
    let items = pboard.pasteboardItems

    if (pboard.types?.contains(NSURLPboardType))! {
        for item in items! {
            if let urlString = item.string(forType: kUTTypeURL as String) {
                self.webViewController.loadURL(text: urlString)
            }
            else
            if let urlString = item.string(forType: kUTTypeFileURL as String/*"public.file-url"*/) {
                let fileURL = NSURL.init(string: urlString)?.filePathURL
                self.webViewController.loadURL(url: fileURL!)
            }
            else
            {
                Swift.print("items has \(item.types)")
            }
        }
    }
    else
    if (pboard.types?.contains(NSPasteboardURLReadingFileURLsOnlyKey))! {
        Swift.print("we have NSPasteboardURLReadingFileURLsOnlyKey")
    }
    return true
}

as no URL is acted upon or error thrown.

mahal tertin
  • 3,239
  • 24
  • 41
slashlos
  • 913
  • 9
  • 17

1 Answers1

1

Yes, the file access is implicit. As the sandbox implementation is poorly documented and had/has many bugs, you want to work around URL and Filenames. The view should register itself for both types at initialisation. Code is in Objective-C, but API should be the same.

    [self registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSURLPboardType, nil]];

Then on performDragOperation:

- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
    BOOL dragPerformed = NO;
    NSPasteboard *paste = [sender draggingPasteboard];
    NSArray *typesWeRead = [NSArray arrayWithObjects:NSFilenamesPboardType, NSURLPboardType, nil];
    //a list of types that we can accept
    NSString *typeInPasteboard = [paste availableTypeFromArray:typesWeRead];

    if ([typeInPasteboard isEqualToString:NSFilenamesPboardType]) {
        NSArray *fileArray = [paste propertyListForType:@"NSFilenamesPboardType"];
        //be careful since this method returns id.  
        //We just happen to know that it will be an array. and it contains strings.
        NSMutableArray *urlArray = [NSMutableArray arrayWithCapacity:[fileArray count]];
        for (NSString *path in fileArray) {
            [urlArray addObject:[NSURL fileURLWithPath:path]];
        }
        dragPerformed = //.... do your stuff with the files;
    } else if ([typeInPasteboard isEqualToString:NSURLPboardType]) {
        NSURL *droppedURL = [NSURL URLFromPasteboard:paste];
        if ([droppedURL isFileURL]) {
            dragPerformed = //.... do your stuff with the files;
        }
    }
    return dragPerformed;
}
mahal tertin
  • 3,239
  • 24
  • 41