During yesterday's MacBook Pro event, Apple announced a fantastic new piece of hardware called the Touch Bar. It's a 1085 x 30 point matte-finish Retina screen that sits above the keyboard on the new MacBook Pros. It can dynamically alter its controls and content as we work in each app on the main screen.

Today we'll look at the basics of adding Touch Bar support to a macOS app. Let's dive in.

First some pre-requisites. You'll need the latest version of Xcode (8.1 at publish time), and the latest version of macOS. Even for those running 10.12.1, this updated 10.12.1 build still needs to be installed to be able to test Touch Bars using Xcode.

After we've made sure we've got the latest versions of everything, we can launch Xcode 8.1 and select Window > Show Touch Bar to see a simulated Touch Bar on screen while we're work on our Mac.

It even floats above all other windows to make it feel a tiny bit more realistic. Neat!

Whew! With that out of the way, we can fire up Xcode and create a new macOS app.

We'll make a new WindowController for our app's initial window, and set its class in Interface Builder.

// WindowController.swift class WindowController : NSWindowController { override func windowDidLoad () { super . windowDidLoad () } }

We'll add an extension to WindowController to adopt the NSTouchBarDelegate protocol. We'll also add an @available statement to make sure it's only available on the latest macOS:

@available(OSX 10.12.1, *) extension WindowController : NSTouchBarDelegate { override func makeTouchBar () -> NSTouchBar ? { // TODO } func touchBar ( _ touchBar : NSTouchBar , makeItemForIdentifier identifier : NSTouchBarItemIdentifier ) -> NSTouchBarItem ? { // TODO } }

Next, we need to create our Touch Bar. We'll do this with an instance of NSTouchBar .

override func makeTouchBar () -> NSTouchBar ? { let touchBar = NSTouchBar () touchBar . delegate = self return touchBar }

We'll use another extension to add some identifiers for the Touch Bar Items we want to appear to NSTouchBarItemIdentifier :

extension NSTouchBarItemIdentifier { static let launch = NSTouchBarItemIdentifier ( "com.magnus.spaceships.launch" ) static let hyperspace = NSTouchBarItemIdentifier ( "com.magnus.spaceships.hyperspace" ) }

Then, we'll set them in the order we want on our touchBar's defaultItemIdentifiers property:

touchBar . defaultItemIdentifiers = [ . launch , . hyperspace ]

Then, we'll implement the sort of "main" function of NSTouchBarDelegate (The "cell for item at index path" of Touch Bars so-to-speak).

We'll switch on our identifiers from earlier, and return an NSTouchBarItem for each one:

func touchBar ( _ touchBar : NSTouchBar , makeItemForIdentifier identifier : NSTouchBarItemIdentifier ) -> NSTouchBarItem ? { switch identifier { case NSTouchBarItemIdentifier . launch : let item = NSCustomTouchBarItem ( identifier : identifier ) item . view = NSButton ( title : "🚀 Launch" , target : self , action : # selector ( launch )) return item case NSTouchBarItemIdentifier . hyperspace : let item = NSCustomTouchBarItem ( identifier : identifier ) item . view = NSButton ( title : "😱 Hyperspace" , target : self , action : # selector ( hyperspace )) return item default : return nil } }

Success!

Last but not least, we can allow our Touch Bar items to be customized by assigning it a customizationIdentifier :

touchBar . customizationIdentifier = NSTouchBarCustomizationIdentifier ( "com.magnus.spaceships" )

if #available(OSX 10.12.1, *) { if (( NSClassFromString ( "NSTouchBar" )) != nil ) { NSApplication . shared () . isAutomaticCustomizeTouchBarMenuItemEnabled = true } }

We'll also need to define which items can be customized:

touchBar . customizationAllowedItemIdentifiers = [ . launch , . hyperspace ]

We can test out customization by selecting View > Customize Touch Bar... from our app's menu.