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
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.
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];
}
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
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.