Jack Humphries
Jack Humphries

Reputation: 13267

Where can a sandboxed Mac app save files?

My Mac app is sandboxed and I need to save a file. Where do I save this file? I can't seem to find the specific place where this is allowed without using an open panel. This is how I do it on iOS:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];

What is the equivalent for the sandboxed directory on Mac?

Upvotes: 29

Views: 11886

Answers (4)

FLUXparticle
FLUXparticle

Reputation: 1183

Is is even easier. For sandboxed apps on macOS the function NSHomeDirectory gives you the path where you have read and write access and can save all your files. It will be a path like this

/Users/username/Library/Containers/com.yourcompany.YourApp

Upvotes: 1

Wizard of Kneup
Wizard of Kneup

Reputation: 2183

Converting @Mazyod's answer into Swift (5.1):

var appPath: URL? {
    //Create App directory if not exists:
    let fileManager = FileManager()
    let urlPaths = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask)
    if let bundleID = Bundle.main.bundleIdentifier, let appDirectory = urlPaths.first?.appendingPathComponent(bundleID,isDirectory: true) {
        var objCTrue: ObjCBool = true
        let path = appDirectory.path
        if !fileManager.fileExists(atPath: path,isDirectory: &objCTrue) {
            do {
                try fileManager.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
            } catch {
                return nil
            }
        }
        return appDirectory
    }
    return nil
}

However, the directory has changed and I am not sure that the additonal repetition of the bundle ID is needed as the path is

"/Users/**user name**/Library/Containers/**bundleID**/Data/Library/Application Support/**bundleID**". 

But it seems to work.

Upvotes: 5

rickster
rickster

Reputation: 126107

That code snippet works on the Mac regardless of whether your application is sandboxed.

In a non-sandboxed Mac app, path will refer to the Documents folder in your home: e.g. /Users/username/Documents.

In a sandboxed app, it refers to a folder within the app sandbox: e.g. /Users/username/Library/Containers/com.yourcompany.YourApp/Documents

See the docs for details.

Upvotes: 30

Mazyod
Mazyod

Reputation: 22559

Apple's Sandboxing guide is very useful, found here.

You basically have a folder dedicated for your app, as described by theAmateurProgrammer in reply to my question here.

~/Library/Container/com.yourcompany.yourappname/

Here is what I have so far, I will improve it later:

//Create App directory if not exists:
NSFileManager* fileManager = [[NSFileManager alloc] init];
NSString* bundleID = [[NSBundle mainBundle] bundleIdentifier];
NSArray* urlPaths = [fileManager URLsForDirectory:NSApplicationSupportDirectory 
                                        inDomains:NSUserDomainMask];

NSURL* appDirectory = [[urlPaths objectAtIndex:0] URLByAppendingPathComponent:bundleID isDirectory:YES];

//TODO: handle the error
if (![fileManager fileExistsAtPath:[appDirectory path]]) {
    [fileManager createDirectoryAtURL:appDirectory withIntermediateDirectories:NO attributes:nil error:nil];
}

Upvotes: 11

Related Questions