NSSavePanel - AccessoryView

Does anyone know how to force the “accessoryview” {ie. fileformat dropdown) on NSSavePanel to show by default? Right now I get an [Options] button that has to be clicked… I know it can be done, everyone else is doing it :slight_smile:

Beats me, maybe a “Swift” thing.

I simply call [NSSavePanel setAccessoryView:] and the panel shows even when the dialog is in “small” mode.

What doesn’t work for me is [NSSavePanel setCanSelectHiddenExtension:], I have a suspicion that it’s been unofficially deprecated, like [NSSearchField centersPlaceholder] was on macOS 10.14, but only officially announced as deprecated in 10.16 API Changes.

Does this make any difference?
https://developer.apple.com/documentation/appkit/nssavepanel/1534515-expanded?language=objc

Well there is no “setAccessoryView” that I could find…

 dialog!.accessoryView = accessoryView

is what I am doing. and expanded only applies to NSSavePanel, but the accessoryview is for both NSOpenPanel and NSSavePanel …

here is what I see

once I clike [OPTIONS] I see this

That’s very different from what I get.

Ah… I’m using it as a sheet… I wonder if that’s the difference. I’ve never tried it as a modal window.

Dave what size does your accessory view have when you create it ?
Header files say the size should be honored ( as well as transitions etc)

This should be the relevant part

 func assign(_ ext:[String]) {
        if ext.count==0 { dialog!.accessoryView = nil; return }
        for i in(0...ext.count-1) {
            zFilter.append("*.\(ext[i].lowercased())")
        }
        let popupButton = NSPopUpButton(frame: NSRect(x: 0, y: 0, width: 70, height: 22),pullsDown: false)
        popupButton.addItems(withTitles:zFilter)
        popupButton.action = #selector(changeFileType(_:))
        popupButton.target = self
        popupButton.selectItem(at: 0)  // Set initial selection:
        let accessoryView =  NSView(frame: NSRect(x: 0, y: 0, width: 80, height: 24))
        accessoryView.addSubview(popupButton)
        dialog!.accessoryView = accessoryView
    }

I have a template class for OPEN and another for CLOSE, from there I spawn all these

func GetOpenFolderItem(filter:[String]) -> folderitem? {
func GetSaveFolderItem(filter:[String],defaultName:String="") -> folderitem? {
func SelectFolder() -> folderitem? {
class OpenDialog : templateOpenDialog {
class SaveAsDialog : templateSaveDialog{
class SelectFolderDialog : templateOpenDialog{
class templateOpenDialog{
class templateSaveDialog{
class fileTYPE {

the assign method is part fo FileType, which is an attribute of both the template classes

UPDATE :
Ok… strange… what I had been testing with was actually NSOpenPanel, and I get that [Options] button. Testing with NSSavePanel… I don’t, I get what I expected

x2

1 Like

Lol, I never thought to check that… ha ha

Its been a few years… but am finalizing this portion of my Swift Framework and found a strange anomoly.

The SaveDialog seems to work just fine… HOWEVER…
when it is in the “small” mode


and I click the down button (to expand the dialog)… instead it DISMISSES it

It starts in expanded mode, and I can compress it, but cannot expand it again :frowning:

I boiled this to the absoulte MINIMUM amount of code, and it still doesn’t work

let dialog          = NSSavePanel()
if (dialog.runModal() ==  NSApplication.ModalResponse.OK) { print("OK") }

does get to the point you have to wonder if theres “something” overlooked or that Apple has left out of docs about this ?

Maybe the default delegate closes ? (that would be odd but …)

I have just read a few dozen articles… and they all show the same thing I already have.
some show a “closure method”… I tried that , same results…
and to make matters worse… it doesn’t “crash”, or throw an exception… if returns “cancel” code

I DID find this in crash log. don’t know what (if anything) it means

Crashing on exception: assertion failed: 'invalid parameter not satisfying: NSWindowAbove == 
ordered' in -[NSViewServiceMarshal addChildWindow:ordered:] on line 1950 of file 
/System/Volumes/Data/SWE/macOS/BuildRoots/38cf1d983f/Library/Caches/com.apple.xbs/Sources/V
iewBridge/ViewBridge-553.1/NSViewServiceMarshal.m

Are you holding on to a reference to the accessoryView? Maybe on expansion it goes out of scope?

not sure that is the issue, but I am testing that now.
I did figure out that I had added extenstions to NSResponder (which is the base class for these panels). That SHOULDn’t affect it, since none of the extenstion members are used.
But if removing the accessory view (as a test) fails. then I will try testing by removing bits of the extension one at a time

Thanks

EDIT :
well its not the accesorry… since just these two lines don’t even work

let dialog          = NSSavePanel()
let _ = dialog.runModal()

BUT… it only fails if compiled along with the rest of my framework. So I am going to focuse on the NSResponder extension now :frowning:

I tried to make a basic project but add the extension code for NSResponder… expecting the panel to fail so I could then work thru the extension to zero in on the specific item causing the problem

However the panel still works… meaning the issue lies in something else my framework is doing… and that is literally 1000’s of lines of code :frowning:

Have you tried using the API that takes a block instead of runModal?

using the closure method?
Yes, with the same results.
If I do this in a barebones (ie. Xcode default project it works)
but if my framework is included it does not.
at first I thought it was the extensions I had for NSObject and NSResponder so those were the first things I disabled… Then I just started commenting out everything that wasn’t required for the framework to compile and run a minimal program. Still nothing.
Tommrowo I will continue to chop away at the framework hoping that I hit “something” that causes it to work…

This is the minimum app code that recreates the problem. I have REMOVED the framework completely and just included the stripped down APP class.
the project consists basically of two files

#1 main.swift (this does NOT use appdelegate file)

import Cocoa
let theApp      = NSApplication.shared
theApp.delegate = app // see App.swift
theApp.run()

#2 the test “app” itself

import Cocoa
import Foundation

let app = App()
class App : dsAPPLICATION {
	override func open() {
		let xx = NSSavePanel()
		let _ = xx.runModal()
	}
} 

open class dsAPPLICATION:  NSObject, NSApplicationDelegate {
	public override init() {
		super.init()
		UserDefaults.standard.set(true, forKey: "NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints")
	}
	open func open()                { print("default: App Open")}
	public func applicationDidFinishLaunching(_ aNotification: Notification) { open() }
}
  • create an Xcode project with these two files
  • run
  • a save dialog will appear
  • if it is expanded, the collapse it (this works)
  • attempt to expand it again… the program terminates