Sandboxed app cannot create folder, save or write to file in user Documents folder

I would like my sandboxed MacOS app to save a log file in a sub-folder of the user's Documents folder, but the app cannot create the sub-folder, create a file or write to an existing file even though I have given the app full disk access via System Preferences-> Privacy. How can I do this?

Replies

macOS has multiple levels of file system access control. See On File System Permissions for an explanation.

Full Disk Access is primarily about MAC; it’s largely irrelevant to a sandboxed app. Rather, sandboxed apps have to follow the rules described in App Sandbox Design Guide. This typically means you have to think about how your file system requirements fit into your user interface:

  • One option is to store your content in your sandbox container and then add a UI that reveals that in the Finder so that the user can easily access it.

  • Alternatively, if you want the user to be in charge of where your content is stored, present a save panel and then persist your access using a security-scoped bookmark. When you present this panel you can set up a default name and a default location that points to the Documents directory.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

@ SimonKravis I also find sandboxing a bit tricky. What I do :

  • ask user to select a folder
  • in the handler, check OK answer
  • then create a NSSavePanel
  • in the handler of the save panel, test for OK.
  • then proceed with creating file
        openPanel.begin() {
            (result) -> Void in
            if result == NSApplication.ModalResponse.OK { 
                let savePanel = NSSavePanel()
                savePanel.title = NSLocalizedString("Some name", comment: "") 
                savePanel.prompt = NSLocalizedString("Create", comment: "")  
                savePanel.allowedFileTypes = ["xxxx"]   // your file types
                let fileManager = FileManager.default   
                
                savePanel.begin() { (result) -> Void in
                    if result == NSApplication.ModalResponse.OK {
                        let fileWithExtensionURL = savePanel.url! 
                        if fileManager.fileExists(atPath: fileWithExtensionURL.path) {
                              // file already exists. Handle properly
                       } else {
                         // do what's needed
                         // then save bookmarks
                            saveBookmarksOnFile() // This is a utility func to write bookmarks
                      }

Utility func:

func bookmarksPath() -> String {  

    var url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as URL
    url = url.appendingPathComponent("Bookmarks.dict")
    return url.path
}

func saveBookmarksOnFile() { 
    let path = bookmarksPath()
    NSKeyedArchiver.archiveRootObject(Global.shared.bookmarks, toFile: path)
}

Hope that helps.