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
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
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
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
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
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
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