Sandbox Revealed
Sample code, ready to use for your sandboxed Mac application

Ever struggled with a Sandoxed app to get it working? Than the sample code here described may be defenetly of interest for you! Sandboxing is a must if you want your app published on the Mac App Store.

The following example has been tested using Xcode 5.02 on Mac OS X 10.9.2 . But it may likely works fine on other versions as well. Your comments or ideas on how to simplify this further are more than welcome!

Accessing files in a Sandbox App

As you may already know, you are not allowed to access files outside of the app sandboxed domain (with the exception of some user folders like Documents, Music, etc.) unless you explicitly request it by using Entitlements.

For example by adding the "com.apple.security.files.user-selected.read-only" entitlement, your application will gain access to the files (or locations) selected by the user (and only to those explicitly selected by the user by means of a NSOpenPanel class!):


NSOpenPanel *openDialog = [NSOpenPanel openPanel];
if ([openDialog runModal] == NSOKButton) {
   NSArray *files = [openDialog URLs];
}


Your app will now have access to the user selected file... as long as it runs. Oh yeah, by closing the app and starting it later on you would have to ask again to the user for the same file location! This is not much of use in case you want to keep the selected file as a user preference.

You can achieve this by using and saving (i.e. in NSUserDefaults) a security scope bookmark of the selected file and using it at any time regardless of application launches. Here how it works, add the "com.apple.security.files.bookmarks.app-scope" entitlement to your app:



// Get bookmarkData from the user selectedFileURL via NSOpenPanel:
NSData *bookmarkData = [selectedFileURL
          bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
   includingResourceValuesForKeys:nil
                    relativeToURL:nil
                            error:&error];
if (!error) {
   ... save here bookmarkData to NSUserDefaults
}
   

Now whenever you need to have access to the user selected file you'll have to convert the bookmark data (previously saved in NSUserDefaults) to a NSURL and use it within a security context:

// Get the file URL from the saved user bookmarkData variable:
NSURL *selectedFileURL = [NSURL URLByResolvingBookmarkData:bookmarkData
               options:NSURLBookmarkResolutionWithSecurityScope
         relativeToURL:nil
   bookmarkDataIsStale:nil
                 error:&error];
if (!error) {
   [selectedFileURL startAccessingSecurityScopedResource];
    ... do something with selectedFileURL
   [selectedFileURL stopAccessingSecurityScopedResource];
}


Tip: you may want to use the entitlement "com.apple.security.files.user-selected.read-write" to gain read and write access to files.
And of course you may also simply bookmark a location and append later a file name:

outputFileURL = [bookmarkedLocationURL URLByAppendingPathComponent:aFilename];



Gaetano Causio © | Privacy Policy | Disclaimer