'SwiftUI: Get sidebar isCollapsed state on macOS

I'm using a NavigationView to create a sidebar on macOS. I can toggle the sidebar using this code:

Button {
    NSApp.keyWindow?.firstResponder?.tryToPerform(
    #selector(NSSplitViewController.toggleSidebar(_:)), with: nil)
}

I'm now trying to display a label while the sidebar is hidden. Triggering this in the button will not work because the user can also hide the sidebar by resizing it.

There is an isCollapsed property on NSSplitViewItem and I assume this is what I might have to check for, but I have no clue how to access it with SwiftUI. Or is there another way to check for sidebar visibility?



Solution 1:[1]

The idea is to find NSSplitViewController (which is still used internally as engine) and subscribe to observe its first split item (which is our sidebar) isCollapsed state.

Tested with Xcode 13.3 / macOS 12.2.1

demo

Here is main part:

  // find split view through hierarchy
  while sview != nil, !sview!.isKind(of: NSSplitView.self) { 
    sview = sview?.superview
  }
  guard let sview = sview as? NSSplitView else { return }
  
  controller = sview.delegate as? NSSplitViewController   // delegate is our controller
  if let sideBar = controller?.splitViewItems.first {     // now observe for state
    observer = sideBar.observe(\.isCollapsed, options: [.new]) { [weak self] _, change in
      if let value = change.newValue {
        self?.sideCollapsed?.wrappedValue = value    // << here !!
      }
    }
  }

and usage like

SideViewInsideNavigationView()
  .background(SplitViewAccessor(sideCollapsed: $collapsed))   // << inject finder !!

Complete findings and code is here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Asperi