Removing/hiding a tracking separator toolbar item

I'm working on adding support in my app for full-height sidebars, as introduced in macOS 11.

The trick is, when the window tab bar is visible, I want to turn the full-height sidebar off. The two don't mix well when the sidebar content is different in each window, as it is in my app. See Xcode for an example of what I want to do (View > Show Window Tab Bar). See Preview for an example of what I want to avoid (open two multi-page PDFs and put them in a single tabbed window).

What's working: I observe the window's tabbedWindows property, and toggle the fullSizeContentView flag in its styleMask accordingly. Thus the window's style updates as needed when I hide and show the tab bar.

What's not working: I need to have a sidebarTrackingSeparator item in my toolbar in order to have some items above the sidebar. But when fullSizeContentView is off, that item appears as a plain separator. I don't want it to be visible at all in that state.

There isn't a straightforward way to hide a toolbar item, especially if it doesn't have a view, which it turns out this one doesn't.

I tried removing the separator item and re-adding it when the window state toggles, but that leads to Cocoa throwing exceptions, complaining that only one tracking item can be registered at a time. This would seem to be a bug, but Xcode manages it somehow.

So how can I properly toggle my window and toolbar state without having that visible separator?

Replies

It looks like I've solved the problem by saving the separator item when I see it in toolbarWillAddItem, and then returning it from toolbar(_:itemForItemIdentifier:willBeInsertedIntoToolbar:) to avoid having a new instance created. That way, removing and re-adding the item works without having exceptions thrown.

The last little snag was to not remove and re-add the separator blindly. The window state may have been preserved across app launches, so I needed to not make assumptions about how the window would initially appear.