Saving file to desktop from macOS app

I've been trying to save the output of a macOS app to my desktop. This is the code I'm using to do so:


let homePath = FileManager.default.homeDirectoryForCurrentUser
let desktopPath = homePath.appendingPathComponent("Desktop")
print(desktopPath)
let filePath = desktopPath.appendingPathComponent("TestFile.txt")
do {
  try unicodeString.write(to: filePath, atomically: false, encoding: .utf8)
} catch {
  errorMessage = error.localizedDescription + "\n" + unicodeString
}


And this is the error I get:


You don’t have permission to save the file “TestFile.txt” in the folder “Desktop”.


The path that's printed looks like this:


file:///Users/DKJ/Library/Containers/com.hatzicware.FileCreator/Data/Desktop


which of course is not on my desktop. How do I construct a path that will let me save the file?


I get the same error running the app both in Xcode, and on its own in Finder.

  • It may not be an answer to this question, But I hope it may help you to save Desktop files organized and save your valuable time.

    I have been using Declutter pro application for more than a year. It performs so well. It is an automatic Mac Desktop Organizing application and Now I can save my Desktop files properly Just within a Click. Hope it may help you.

Add a Comment

Accepted Reply

Turn off the sandbox or use NSSavePanel.

Replies

Turn off the sandbox or use NSSavePanel.

Sandbox is really very strict. You are in the sandbox, you cannot play outside without authorization. You have a local desktop inside the sandbox, but the one of the yard !


So, you need first to authorize access, then save to the selected folder.


I ended up with the following scheme to create a file in an outside folder:

- openPanel first, to declare a folder to authorize

- I inform user about this

- in its completion, call savePanel.


Here it is, for an action called from a menuItem:


    @IBAction func newDossier(_ sender: NSMenuItem) {

        let openPanel = NSOpenPanel()       // Authorize access in sandboxed mode
        openPanel.message = NSLocalizedString("Select folder where to create file\n(Necessary to manage security on this computer)", comment: "enableFileMenuItems")
        openPanel.prompt = NSLocalizedString("Select", comment: "enableFileMenuItems")
        openPanel.canChooseFiles = false    // Only select or create Directory here ; you can select the real Desktop
        openPanel.canChooseDirectories = true
        openPanel.canCreateDirectories = true
        openPanel.begin() {                              // In the completion, Save the file
            (result2) -> Void in
            if result2 == NSApplication.ModalResponse.OK {
                storeBookmark(url: openPanel.url!)          // Save the bookmark for future use if needed

                let savePanel = NSSavePanel()
                savePanel.title = NSLocalizedString("File to create", comment: "enableFileMenuItems")
                savePanel.nameFieldStringValue = ""
                savePanel.prompt = NSLocalizedString("Create", comment: "enableFileMenuItems")
                savePanel.allowedFileTypes = ["xxxx"]   // if you want to specify file signature
                let fileManager = FileManager.default
        
                savePanel.begin() { (result) -> Void in
                    if result == NSApplication.ModalResponse.OK {
                        let fileWithExtensionURL = savePanel.url!  //  May test that file does not exist already
                        if fileManager.fileExists(atPath: fileWithExtensionURL.path) {
                        } else {
                                       // Now, write the file
                    }
                }
            }
        }
    }
}

Did you finally solve your issue ?

Using NSSavePanel did the trick. Thanks!

Yes, NSSavePanel was all I needed.