Matt
Matt

Reputation: 822

NSSplitView Collapse Event

I'm trying to implement an NSSplitView similar to Xcode where you can collapse a view by dragging its handle to under half its width and it will collapse automatically. I have that part working, but I need to update the state of a button in the toolbar when this happens. I tried listening to splitViewDidResizeSubviews and checking if the splitView's view is collapsed, but that method fires 16 times with collapsed == true, so I don't think I want to update the button's state 16 times. Is there a cleaner way to do this? I'm new to Cocoa, but from what I've seen, I would expect there to be some way to just say bind this button's state to the isCollapsed property and be done with it. Does such a thing exist?

Upvotes: 1

Views: 862

Answers (3)

jeff-h
jeff-h

Reputation: 2624

If you subclass your NSSplitViewController you can add a listener for the SplitViewItem's isCollapsed property:

class MySplitViewController: NSSplitViewController {

    var observer: NSKeyValueObservation?

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do view setup here.

        let sideViewSplitViewItem = splitViewItems[0]

        observer = sideViewSplitViewItem.observe(\.isCollapsed, options: [.initial, .new]) {splitViewItem, _ in
            print("Sidebar collapsed state changed to: \(splitViewItem.isCollapsed)")
        }
    }

}

Upvotes: 1

tjgrant
tjgrant

Reputation: 438

While NSSplitView has no event or observable property for when one of it's subviews is "collapsed", the immediate subview itself will have its hidden property set to YES.

So you can either observe the subview's hidden property yourself, or if you're creating your own custom subview of NSView, you can override the -(void) setHidden:(BOOL)hidden to catch the event.

I do the latter, and it works correctly every time.

-(void)setHidden:(BOOL)hidden
{
    [super setHidden:hidden];

    // Insert code to react to the "collapsed" event here.
    // (You're likely going to tell your parent view,
    // self.window.windowController, or something.)
}

Of course the setHidden method / hidden property can in theory be called for purposes other than from NSSplitView "collapsing" your view, but this is very unlikely to ever happen in practice.

Upvotes: 0

Paul Patterson
Paul Patterson

Reputation: 6918

The best way to see what bindings are available is to check the docs, specifically the Cocoa Bindings Reference (look in the sidebar for the view you're after).

enter image description here

NSSplitView doesn't have the binding you describe, so I think you're on the right track with your current approach. Of course, you don't need to update the button's state sixteen times, just check it's value each time, and update it if needs be. It might seem a bit wasteful, but checking the value of a bool is a very cheap operation, and you won't notice any kind of performance hit.

Upvotes: 0

Related Questions