macOS Sandbox — Bookmark file system paths to avoid asking for access each time your app launches.

Chris Paynter
3 min readFeb 22, 2021

When releasing an app to the Mac App store, it must be in an App Sandbox.

One requirement of being in an app in a sandbox (among many others) is that your users must explicitly grant access to file system locations.

As you will see, this is very easy to achieve.

However, a slightly trickier part is being able to repeatedly access these locations on behalf of the user when the app relaunches, without having to ask the user again.

This of course is a common app requirement. For example, during app setup you might ask the user for a directory to read data from, which would remain the same for the remainder of the user’s use of the app. It would be a real drag to have to ask the user to choose that location each time they open the app.

Luckily it’s also not too difficult to preserve this previously granted access, using URL bookmarks.

Let’s have a look at how we can do it. I’ll step by step show you some code extracts from an exampleAppDelegate.swift file that I’ve included in full at the bottom.

Asking the user for a file system location

The askUserForDirectory method uses NSOpenPanel to show the user a file picker. I’ve locked it to just allow directory picking. Once that has been selected, we pass the URL to a helper method which just iterates the files and directories and prints their path.

As per Apple’s docs for NSOpenPanel:

When the user chooses a file to open, macOS adds that file to the app’s sandbox.

The fact is that when the user manually chooses the location via the NSOpenPanel dialogue, the system considered this to be an explicit authorisation for your app to access that directory.

Thus, once the URL is added to your sandbox via the panel, you can instantly start using it to read and open files.

Of course, as mentioned, this doesn’t last forever. If we want to reuse this file system URL on next app launch without showing this dialogue panel again, we must bookmark it.

Saving access to this location for later use

Once we have the URL to the location the user selected, we can then create a bookmark to it, and persistently store it for later retrieval when the app relaunches.

This if fairly trivial to do when we UserDefaults.

We just need to extend the askUserForDirectory function slightly with the following code:

bookMarkKey is a simple string constant.

Lastly, we check for the existing bookmark

When the app launches, we now need to check UserDefaults to see if the user has previously granted permission. Based on that we either go on our merry way and access the location, or we ask the user to choose the location.

If we find an entry in UserDefaults, we pass it to the URL overide which builds urls based on raw bookmark data.

If that is created successfully, and the bookmark is not stale, then we can start to use the bookmark.

To do so, we must do so within a security scope that we explicitly start and stop using startAccessingSecurityScopedResource and it’s stop equivalent.

Most error handling is omitted here, but you will see that in the event UserDefaults has not got an entry for the bookmark, we call the previous described askUserForDirectory method.

In reality, most errors below would likely need to result in a call to that method.

The completed code

Here’s the complete AppDelegate.swift file.

You should be able to just drop this into a brand new AppKit App Delegate templated mac app (when you create a new project in Xcode), and run it.

--

--

Chris Paynter

Software architect/engineer. Technology enthusiast. Australia born, Finland based. Maker and owner at Solanne Technology — solanne.io