Search code examples
swiftxcodemacoscocoaappkit

Open Downloads Directory With Finder Prompting User for Permission If Necessary


I'm building a BitTorrent client where I give the user an option, through a context menu, to open the containing directory of a torrent.

To do so, I tried using open(_) method of an NSWorkspace instance like so:

NSWorkspace.shared.open(directory)

where directory is an URL instance pointing to a directory, like so:

let directory = URL(fileURLWithPath: item.parentPath, isDirectory: true)

Here, item.parentPath is a String holding an absolute path.

Now, let me clear up that the code runs fine. It successfully opens up the directories I want inside Finder (since it's the default application for opening directories).

However, if the directory happens to be the Downloads directory of the user, it displays this prompt:

Operation rejected due to lack of permissions.

Again, this is alright since my application does not have permission to open the Downloads directory. However, I want to attempt to open the directory, asking for permission, just like any other application on macOS, like so:

Prompting for permission.

I looked up in the docs and found this method of NSWorkspace: open(_:withApplicationAt:configuration:completionHandler:). I thought it was great since I could set the promptsUserIfNeeded property of an NSWorkspace.OpenConfiguration instance to true, which I believe should make my application politely ask for permission to open the directory if needed.

Here's my resulting code:

let url = URL(fileURLWithPath: item.parentPath, isDirectory: true)

let configuration: NSWorkspace.OpenConfiguration = NSWorkspace.OpenConfiguration()
configuration.promptsUserIfNeeded = true

let finder = NSWorkspace.shared.urlForApplication(withBundleIdentifier: "com.apple.finder")

// Open file with default application
NSWorkspace.shared.open([url], withApplicationAt: finder!, configuration: configuration)

Sadly, it's making no difference. I'm still getting the same dialog as shown in the first image.

I want to know two things:

  1. What am I doing wrong?
  2. How can I open a directory, prompting for permissions if necessary?

Solution

  • I am assuming you want this all to play nicely within the sandbox. You have two choices:

    1. Use activateFileViewerSelecting(_:) or selectFile(_:inFileViewerRootedAtPath:). Either of these will prompt for permission, & once gained, you can return to using open(_:withApplicationAt:configuration:completionHandler:), if you so wish.

    2. Use Security-Scoped Bookmarks and Persistent Resource Access.