Bad layout constraints when adding accessory view to Open/Save dialog

Viewed 556

I'm trying to add a simple NSView with a checkbox as an accessory view to an NSOpenPanel, but when I run my program, I get an error saying The Open/Save panel was supplied an accessory view with bad layout constraints, resulting in a view that is zero [height/width]. Here are the constraints I've added to the view: constraints for NSView And here are the constraints for the checkbox: constraints for checkbox

Here's the code for creating the NSOpenPanel:

let dlgOpenSounds: NSOpenPanel = NSOpenPanel()
let optionsView = BatchAddOptionsView()
dlgOpenSounds.accessoryView = optionsView
dlgOpenSounds.accessoryView?.awakeFromNib()
let result = dlgOpenSounds.runModal()
if result == .OK {
    // do stuff
}

Anyone know what I'm doing wrong?

2 Answers

I ran into the same issue with a similar arrangement created in code, and finally worked it out. My implementation is handled in a custom NSView subclass, which I then add as the NSOpenPanel's .accessoryView from the view controller where I display the panel.

private func setup() {
    hiddenFilesCheckbox = NSButton(checkboxWithTitle: "Show Hidden Files", target: self, action: #selector(hiddenFilesCheckboxValueChanged))
    guard let checkbox = hiddenFilesCheckbox else {
        os_log("Hidden files checkbox is nil")
        return
    }
    addSubview(checkbox)
    checkbox.translatesAutoresizingMaskIntoConstraints = false

    checkbox.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 12).isActive = true
    checkbox.topAnchor.constraint(equalTo: self.topAnchor, constant: 12).isActive = true
    self.heightAnchor.constraint(greaterThanOrEqualToConstant: frame.height).isActive = true
    self.widthAnchor.constraint(greaterThanOrEqualToConstant: frame.width).isActive = true
}

"hiddenFilesCheckbox" is declared as a property of my custom NSView subclass. I played around with some other hard-coded values for the constants, but these worked best in my tests. I pass in the openPanel to the subclass's initializer to use its frame to set the accessoryView's width. I used a hard-code value of 40 for the height in the initializer that isn't included here. After setting up the accessory view with these constraints, the warnings stopped appearing and the accessory view appears as desired/expected.

Try setting up the view like this (Xcode 10.1). First make sure that AutoLayout on the view is not selected. Then:

accessory view size inspector

Change the view width and height to whatever is appropriate (I'm using a 'small' control size)

Setup the checkbox similar to:

accessory view control size inspector

Again, adjust the width and height as necessary. No other constraints should be added.

Note that if you save and reuse the accessory view in multiple panel.beginModalSheet() calls, you'll get a console warning because the previous beginModalSheet() added layout constraints.

Related