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.

Leave a rating/review
Save for later
Share
You are currently viewing page 2 of 2 of this article. Click here to view the first page.

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:

  1. A new item was created to show a label for ratings.
  2. 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 the delegate, 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.

Rating Items

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:

  1. This creates a simple label, just like in previous steps.
  2. 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.
  3. 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.

Final Touch Bar

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.

Screen Shot 2016-10-31 at 5.33.58 PM (2)

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:

  1. How to setup your app to show a Touch Bar
  2. How to present static labels in a Touch Bar
  3. How to add dynamic labels in a Touch Bar using binding
  4. 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!