Sample Code

Integrating a Toolbar and Touch Bar into Your App

Build a toolbar in your app’s window, with a corresponding Touch Bar, for quick access to app features.

Download

Overview

A Toolbar manages the space immediately below a window’s title bar and above your app’s custom content. Toolbars manage controls that apply to the content into a window.

Each item in the toolbar is represented by an NSToolbarItem object, created by Interface Builder or in code. This sample shows you how to integrate a toolbar into an NSWindow.

Create the Toolbar

Add a toolbar to your window by dragging an NSToolbar object from Xcode’s Library window onto your NSWindow object. Then connect the toolbar object to the window controller and make it the NSToolbarDelegate.

Assign Toolbar Identifiers

For each NSToolbarItem you create, you must assign a unique identifier of type NSToolbarItemIdentifier. AppKit has predefined, built-in toolbar item identifiers for cloud sharing, printing, and showing the font and color palette. All toolbar items are arranged within the toolbar in an order determined by the user, and the order is autosaved as part of the toolbar’s configuration.

This sample creates two identifiers: one for setting the font size and one for setting the font style of an NSTextView.

private extension NSToolbarItem.Identifier {
    static let fontSize: NSToolbarItem.Identifier = NSToolbarItem.Identifier(rawValue: "FontSize")
    static let fontStyle: NSToolbarItem.Identifier = NSToolbarItem.Identifier(rawValue: "FontStyle")
}

Create the Allowed Toolbar Items

Implement toolbarAllowedItemIdentifiers: as a required function to return an array of toolbar item identifiers for the toolbar, specifying the contents and the order of the items in the configuration palette.

func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
    return [ NSToolbarItem.Identifier.fontStyle,
             NSToolbarItem.Identifier.fontSize,
             NSToolbarItem.Identifier.space,
             NSToolbarItem.Identifier.flexibleSpace,
             NSToolbarItem.Identifier.print ]
}

Create the Default Toolbar Items

Implement toolbarDefaultItemIdentifiers: to provide the default set of items that initially appear in the toolbar.

func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
    return [.fontStyle, .fontSize]
}

Create a Toolbar Item from an Identifier

As the toolbar delegate, you are responsible for creating a toolbar item for each identifier you define. At the time that AppKit instructs you to create an NSToolbarItem, you create one based on the identifier. Implement toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar: to return the two toolbar items: Font Style and Font Size.

func toolbar(
    _ toolbar: NSToolbar,
    itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier,
    willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
    
    var toolbarItem: NSToolbarItem = NSToolbarItem()
    
    /**Create a new NSToolbarItem, and then go through the process of setting up its
    attributes from the master toolbar item matching that identifier in the dictionary of items.
     */
    if itemIdentifier == NSToolbarItem.Identifier.fontStyle {
        // 1) Font style toolbar item.
        toolbarItem =
            customToolbarItem(itemForItemIdentifier: NSToolbarItem.Identifier.fontStyle.rawValue,
                              label: NSLocalizedString("Font Style", comment: ""),
                              paletteLabel: NSLocalizedString("Font Style", comment: ""),
                              toolTip: NSLocalizedString("tool tip font style", comment: ""),
                              itemContent: styleSegmentView)!
    } else if itemIdentifier == NSToolbarItem.Identifier.fontSize {
        // 2) Font size toolbar item.
        toolbarItem =
            customToolbarItem(itemForItemIdentifier: NSToolbarItem.Identifier.fontSize.rawValue,
                              label: NSLocalizedString("Font Size", comment: ""),
                              paletteLabel: NSLocalizedString("Font Size", comment: ""),
                              toolTip: NSLocalizedString("tool tip font size", comment: ""),
                              itemContent: fontSizeView)!
    }
    
    return toolbarItem
}

Each toolbar receives its own distinct set of identifiers. If a toolbar item has a custom view, that view should be in place when the item is returned. Do not assume that the returned item is added as an active toolbar item. In fact, the toolbar may ask for items here to construct the customization palette (it makes copies of the returned items). If willBeInsertedIntoToolbar is true, the returned item is inserted, and eventually the toolbarWillAddItem: delegate is called.

Use a Custom View for a Toolbar Item

When you apply a custom view to an NSToolbarItem, you place one or more controls together to represent that NSToolbarItem. In this sample, the custom views included are the font-style segmented control and the font size control, consisting of a label, stepper, and edit field.

Add More Attributes to a Toolbar Item

Use the optional toolbarWillAddItem: delegate function. This function is called when a new item is about to be added to the toolbar. At this time, you add or change initial state information for toolbar items, particularly those that you don’t directly control, like NSToolbarPrintItemIdentifier. In this sample, you add a tooltip string to the print toolbar item.

Customize the Toolbar

You implement the delegate function toolbarAllowedItemIdentifiers to determine which toolbar items users place in the toolbar. Users customize the item ordering by either control-clicking the toolbar, or by choosing Customize Toolbar from the View menu. This option opens a customization alert, where the user changes the layout. Only items returned by the delegate function toolbarAllowedItemIdentifiers appear in that alert.

Add Touch Bar Support

This sample implements the Touch Bar to work in conjunction with the toolbar. What you see in the window’s toolbar is what you see in the Touch Bar. This sample uses the Touch Bar to set the font style and size the same way as the toolbar.

Override makeTouchBar() and create the NSTouchBar.

override func makeTouchBar() -> NSTouchBar? {
    let touchBar = NSTouchBar()
    touchBar.delegate = self
    touchBar.customizationIdentifier = .touchBar
    touchBar.defaultItemIdentifiers = [.fontStyle, .popover, NSTouchBarItem.Identifier.otherItemsProxy]
    touchBar.customizationAllowedItemIdentifiers = [.fontStyle, .popover]
    
    return touchBar
}

Test the Touch Bar on a MacBook Pro. If you’re unable to do so, however, you may use Xcode’s Touch Bar simulator by choosing Window > Show Touch Bar.

Customize the Touch Bar

The user customizes the Touch Bar by choosing Customize Touch Bar from the View menu. To add this menu item to the main menu, implement the following:

NSApplication.shared.isAutomaticCustomizeTouchBarMenuItemEnabled = true

See Also

First Steps

NSTouchBar

An object that provides dynamic contextual controls in the Touch Bar of supported models of MacBook Pro.

NSTouchBarDelegate

A protocol that allows you to provide the items for a bar dynamically.

NSTouchBarProvider

A protocol that an object adopts to create a bar object in your app.