loading...
Cover image for Adding a Unified `NSToolbar` to a SwiftUI window

Adding a Unified `NSToolbar` to a SwiftUI window

hugh_jeremy profile image Hugh Jeremy ・2 min read

Previously on "Adventures in SwiftUI", I discussed adding an NSTableView to a SwiftUI project. I received a follow up question from Axel:

To be honest, I don't have the faintest idea how I did this. So, I'll dig through the code and blog the process. That way, if anyone else has the same question, Google will hopefully land them here.

First stop, where do we create the NSWindow?

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    var window: NSWindow!


    func applicationDidFinishLaunching(_ aNotification: Notification) {
    // Snip

It's declared in the AppDelegate. I can't recall if all SwiftUI apps depend on the AppDelegate pattern... If yours does not, then the following is probably still useful, but you will likely need to adapt to your circumstances.

Here is the point of NSWindow creation:

// Enclosing code snipped
window = NSWindow(
    contentRect: NSRect(x: 0, y: 0, width: 640, height: 480),
    styleMask: [
        .titled,
        .unifiedTitleAndToolbar,
        .closable,
        .miniaturizable,
        .resizable,
        .fullSizeContentView
    ],
    backing: .buffered,
    defer: false
)
window.center()
window.title = "Draft Sport"
window.titleVisibility = .hidden
window.setFrameAutosaveName("Draft Sport")
window.contentView = NSHostingView(rootView: contentView)

The key thing to note here is the provision of the .unifiedTitleAndToolbar mask in the style mask array.

Next, we need to create the actual toolbar content.

// Enclosing code snipped
let toolbarButtons = NSHostingView(rootView: ToolbarButtons())
toolbarButtons.frame.size = toolbarButtons.fittingSize

let titlebarAccessory = NSTitlebarAccessoryViewController()
titlebarAccessory.view = toolbarButtons
titlebarAccessory.layoutAttribute = .trailing

Finally, we add the titlebarAccessory to the NSWindow instance:

// Enclosing code snipped
window.toolbar = NSToolbar()
window.addTitlebarAccessoryViewController(titlebarAccessory)

And voila, you've got a unified toolbar. Watch out though: I haven't gone any further with this. I imagine there are going to be all sorts of challenges developing the typical behaviour expected of a unified toolbar.

I hope this helps you Axel, and anyone else enjoying SwiftUI!

Hugh

Posted on Mar 30 by:

hugh_jeremy profile

Hugh Jeremy

@hugh_jeremy

Making farm robots (https://thornleighfarm.com) & accounting APIs (https://amatino.io).

Discussion

markdown guide
 

Thanks You !

it's fine, I just forgot the window.toolbar = NSToolbar ()