How to Use NSTouchBar on macOS
Learn how to use the new NSTouchBar APIs to add Touch Bar support for your macOS apps. By Andy Pereira.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
How to Use NSTouchBar on macOS
15 mins
Text Fields and Scrubbers
In makeTouchBar()
, change the defaultItemIdentifiers
to the following:
touchBar.defaultItemIdentifiers = [.infoLabelItem, .flexibleSpace, .ratingLabel, .ratingScrubber]
This will allow the Touch Bar to show three new items: a label and a scrubber. You’ve also added a .flexibleSpace
. This is a dynamically sized space put in the Touch Bar to keeps things grouped together nicely. You can also take advantage of .fixedSpaceSmall
, and .fixedSpaceLarge
for more static sized spacing.
You’ll still need to customize these items, just like the label you added. Add the following cases
to the switch
in touchBar(_:makeItemForIdentifier:)
:
case NSTouchBarItemIdentifier.ratingLabel:
// 1
let customViewItem = NSCustomTouchBarItem(identifier: identifier)
customViewItem.view = NSTextField(labelWithString: "Rating")
return customViewItem
case NSTouchBarItemIdentifier.ratingScrubber:
// 2
let scrubberItem = NSCustomTouchBarItem(identifier: identifier)
let scrubber = NSScrubber()
scrubber.scrubberLayout = NSScrubberFlowLayout()
scrubber.register(NSScrubberTextItemView.self, forItemIdentifier: "RatingScrubberItemIdentifier")
scrubber.mode = .fixed
scrubber.selectionBackgroundStyle = .roundedBackground
scrubber.delegate = self
scrubber.dataSource = self
scrubberItem.view = scrubber
scrubber.bind("selectedIndex", to: self, withKeyPath: #keyPath(rating), options: nil)
return scrubberItem
Step by step:
- A new item was created to show a label for ratings.
- Here, a custom item is created to hold an
NSScrubber
. This is a new control introduced for the Touch Bar. They behave similar to a slider, but can be customized specifically for working in the bar. Since scrubbers require a delegate to handle events, all you need to do here is set thedelegate
, which ViewController already has implemented for you.
Build and run, and you’ll now see two new items in your Touch Bar. Notice that when you select an item from the scrubber, it will adjust the value in the app’s window.
Segmented Controls
Next, you’re going to add a segmented control to the application. Since this doesn’t work using the delegate pattern, you’ll get a chance to see how to set up a Target-Action within the Touch Bar. Back in makeTouchBar()
, you’ll need to add the last three items to defaultItemIdentifiers
:
touchBar.defaultItemIdentifiers = [.infoLabelItem, .flexibleSpace, .ratingLabel, .ratingScrubber, .flexibleSpace, .visitedLabelItem, .visitedItem, .visitSegmentedItem]
And add the last three cases
to touchBar(_:makeItemForIdentifier:)
:
case NSTouchBarItemIdentifier.visitedLabelItem:
// 1
let customViewItem = NSCustomTouchBarItem(identifier: identifier)
customViewItem.view = NSTextField(labelWithString: "Times Visited")
return customViewItem
case NSTouchBarItemIdentifier.visitedItem:
// 2
let customViewItem = NSCustomTouchBarItem(identifier: identifier)
customViewItem.view = NSTextField(labelWithString: "--")
customViewItem.view.bind("value", to: self, withKeyPath: #keyPath(visited), options: nil)
return customViewItem
case NSTouchBarItemIdentifier.visitSegmentedItem:
// 3
let customActionItem = NSCustomTouchBarItem(identifier: identifier)
let segmentedControl = NSSegmentedControl(images: [NSImage(named: NSImageNameRemoveTemplate)!, NSImage(named: NSImageNameAddTemplate)!], trackingMode: .momentary, target: self, action: #selector(changevisitedAmount(_:)))
segmentedControl.setWidth(40, forSegment: 0)
segmentedControl.setWidth(40, forSegment: 1)
customActionItem.view = segmentedControl
return customActionItem
For each step:
- This creates a simple label, just like in previous steps.
- Here, you create another label, but you bind the value of the text to a property. Just like the scrubber, binding values to make updating Touch Bar items very easy.
- Finally, you create a segmented control to be displayed in a touch bar item. You can see that setting up a target and action is just the same as it always is.
Build and run, and you’ll see that you can interact with not only the scrubber, but the segmented control as well. Not only that, values changed in the Touch Bar are reflected in the window, and vice-versa.
Colored Buttons
Finally, it would be nice to give the user a chance to save using the Touch Bar. Since this button has a different outcome from the others, you’ll take advantage of the new bezelColor
property of NSButton
to give it some color.
To do this, open TouchBarIdentifiers.swift, and in the NSTouchBarItemIdentifier
extension, add the following to the end:
static let saveItem = NSTouchBarItemIdentifier("com.razeware.SaveItem")
This creates a new identifier from scratch, which will allow you to add a new button to the Touch Bar.
Go back to ViewController.swift, and add a new .flexSpace
and .saveItem
to the touch bar’s defaultItemIdentifiers
:
touchBar.defaultItemIdentifiers = [.infoLabelItem, .flexibleSpace, .ratingLabel, .ratingScrubber, .flexibleSpace, .visitedLabelItem, .visitedItem, .visitSegmentedItem, .flexibleSpace, .saveItem]
You’re almost done – all you have left is to handle configuring the new item. In touchBar(_:makeItemForIdentifier:)
, add a final case
before default
:
case NSTouchBarItemIdentifier.saveItem:
let saveItem = NSCustomTouchBarItem(identifier: identifier)
let button = NSButton(title: "Save", target: self, action: #selector(save(_:)))
button.bezelColor = NSColor(red:0.35, green:0.61, blue:0.35, alpha:1.00)
saveItem.view = button
return saveItem
Everything here should look pretty familiar to this point. All that is new is setting the bezelColor
to a familiar green :].
Build and run, and you’ll see that you have a nice green button, and it has the same behavior as the Save button in the window.
Where To Go From Here?
You can download the final sample project here.
That’s it for learning the basics of the Touch Bar. It should be pretty clear Apple wanted to make this easy for you to get started to quickly make these features available to your users.
In this tutorial, you learned the following:
- How to setup your app to show a Touch Bar
- How to present static labels in a Touch Bar
- How to add dynamic labels in a Touch Bar using binding
- How to add controls to a Touch Bar, and handle their events
Don’t stop with these examples! There are plenty of exciting features to be found within NSTouchBar
and NSTouchBarItem
. Try adding a popover to your Touch Bar, or see how easy it is to format text in your app. You can also check out creating Touch Bars in Interface Builder.
If you have any questions, comments, or want to just want to rave (or complain) about the new MacBook Pro, please join the forum discussion below!