0

I have code in my macOS app that shows a save dialog using NSSavePanel. I want the panel to always open in a specific directory that I send as a parameter to my function. (e.g., /User/Desktop).

Here’s the simplified version of my code:

- (NSURL *)doSave:(NSURL *)initialLocation
     withFileName:(NSString *)fileName
         withTitle:(NSString *)title
{
    NSSavePanel *_savePanel = [NSSavePanel savePanel];

    // I want to force it to open here:
    [_savePanel setDirectoryURL:initialLocation];
    [_savePanel setNameFieldStringValue:fileName];
    [_savePanel setTitle:title];

    if ([_savePanel runModal] == NSModalResponseOK) {
        return [_savePanel URL];
    }
    return nil;
}

On macOS Sonoma (14) and earlier, this worked: The dialog always opened at initialLocation.

But on macOS Sequoia (15), the panel always opens at the last location where a file was saved (system-wide), even though I set directoryURL.

I tried:

  1. Clearing the identifier (_savePanel.identifier = nil)

  2. Setting _savePanel.restorable = NO.

  3. Clearing NSUserDefaults keys like NSNavLastRootDirectory.

  4. Resetting directoryURL right before runModal.

But Sequoia still restores the last-used location, seemingly overriding directoryURL.

How can I force NSSavePanel to honour setDirectoryURL: on Sequoia (macOS 15)? Did Apple change the expected way to set the initial directory? Is there a new API or flag to disable the "last-used folder" behaviour?

Additional observation (LLDB):

// Right after creating the save panel:
(lldb) po [_savePanel directoryURL]
file:///User/Documents/    // Last used folder 

// After calling setDirectoryURL:initialLocation:
(lldb) po [_savePanel directoryURL]
nil                       // My assignment was wiped out

I found out that if I use the old API setDirectory: (which is deprecated), the panel does open in the folder we specify and doesn’t get overridden by the system. But I can't rely on a deprecated API.

6
  • I tried your code and it works for me. How is the URL created? Does your app already have permission to write in the directory? Is the app sandboxed? Commented Jul 30 at 7:59
  • @Willeke My app is sandboxed. It has permission to write in the directory. I am using Xcode 16.4 with Tahoe. Also, the deprecated API "setDirectory" is working just fine. Commented Jul 31 at 5:21
  • setDirectory: isn't deprecated API, it's just replaced by a different notation. Have you tried building on macOS 15? Post a minimal reproducible example please. Commented Jul 31 at 5:45
  • @Willeke If this is written in the appkit's header : - (void)setDirectory:(nullable NSString *)path API_DEPRECATED("Use -setDirectoryURL: instead", macos(10.0,10.6)); does it not mean its deprecated and can throw error in future? Yes I tried on macOS 15 and it still doesn't work. Commented Jul 31 at 6:41
  • Sorry, I didn't read it properly and mixed it up setDirectory: and setDirectoryURL:. setDirectoryURL: is replaced by property directoryURL but does the same. Commented Jul 31 at 9:57

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.