An object that provides dynamic contextual controls in the Touch Bar of supported models of MacBook Pro.
- macOS 10.12.2+
- UIKit for Mac 13.0+Beta
On supported MacBook Pro models, the Touch Bar, above the keyboard, shows instances of the
NSTouch class from the front-most app. Such an instance is called, simply, a bar. You define a bar to provide controls relevant to the user’s context. Each such control is an instance of the
NSTouch class, called, simply, an item.
You can provide many bars within your app, one for each responder instance; macOS frameworks can provide bars, as well, that can appear alongside your app’s bars. The system determines which bars to show at any given time. For example, an app that uses standard AppKit objects, such as text fields (instances of the
NSText class), obtains appropriate bars along with relevant items automatically.
Refer to the following sample code projects which demonstrate how to use
NSTouch and related classes, including the
NSScrubber class, with its rich API that lets you build a highly-customized picker control:
NSTouchBar Catalog—Shows how to create bars and items for use in the Touch Bar
NSToolBar Sample—Shows how to add Touch Bar support to a typical Mac app
To use the Touch Bar, define bars in objects in your app’s responder chain, as described in NSTouchBar Objects. At run time, the system traverses up the responder chain to discover, combine, and show bars from your app and from frameworks you link against.
You can configure a bar to support dynamic composition, in which the system shows the bar in an expanded form that contains items from bars lower in the responder chain (that is, from closer to the first responder). Because of dynamic composition and placement of items shown on the Touch Bar, always ensure that your bars appear as you expect them to, testing on the versions of macOS that you support.
Instances of the
NSTouch class employ gesture recognizers and take advantage of macOS 10.12.1 event enhancements. Because of the physical geometry of the Touch Bar, touch events passed to gesture recognizers have only a meaningful x, or horizontal, component.
There is no need, and no API, for your app to know whether or not there is a Touch Bar available. Whether your app is running on a machine that supports the Touch Bar or not, your app’s onscreen user interface (UI) appears and behaves the same way.
The Touch Bar is a Retina display, like the screen of a MacBook Pro. To perform custom drawing or animation within the Touch Bar, follow the same best practices that you would on the screen. Be sure to read Performance Considerations for the Touch Bar.
On the right side of the Touch Bar, the system supplies the always-available Control Strip. The Control Strip gives the user access to standard controls for display brightness, sound volume, Siri, and so on. Your app’s bars appear to the left of the Control Strip. The user can choose to hide the Control Strip, which gives the frontmost app the entire Touch Bar width. Read about how bars respond to available width in NSTouchBar Layout.
To the right of the Control Strip is a Touch ID sensor. To use Touch ID on supported MacBook Pro models, use methods from the LocalAuthentication framework.
The Touch Bar dims automatically and wakes when the user touches it. Do not show alerts in the Touch Bar, and do not use the Touch Bar for widgets.
You can think of an
NSTouch object (or bar), with its array of
NSTouch objects (or items), as analogous to a window toolbar with its toolbar items, or a menu with its menu items.
To provide a bar in your app, define it in an object that meets three requirements. The object that defines the bar must:
Be a responder (an instance of an
NSRespondersubclass) that is present within a responder chain at runtime.
The built-in responder classes conform to the
NSTouch protocol and support key-value observing (KVO), both of which are used and required by the
NSTouch infrastructure. In the context of Touch Bar support, a responder instance can also be called a bar provider.
Listing 1 shows an example implementation of the
make delegate method. In this code snippet, you can see some statements related to customization. Bars support user customization, as described in NSTouchBar Customization.
You can take advantage of built-in KVO support to keep track of bar state, such as which items are visible as the user customizes and interacts with the Touch Bar.
If you explicitly adopt the
NSTouch protocol in the app delegate or in a window delegate, you must also explicitly send the associated key-value observing notifications from within your implementations of
NSTouch methods; this lets the system respond appropriately to changes in the bar. To avoid the need to manually support KVO, use the app object as a bar provider, instead of the app delegate, or use a window controller or window as a bar provider, instead of the associated window delegate.
To programmatically invalidate a bar associated with a bar provider, such as because you are changing the bar’s state, set its
touch property to a value of
Using NSTouchBarItem Objects
A bar itself (an
NSTouch object) has no visible representation in a MacBook Pro Touch Bar. A user instead sees the bar’s items, each of which is an instance of the
The items presented in a bar are the elements in a private array owned by the bar. To specify the items for a bar, you do not fill this array directly, but rather rely on the bar to manage its items based on various groups of items and item identifiers that you do specify directly.
In specifying items for a bar you have two options, giving you flexibility for optimizing resource use and efficiency in your app.
templateproperty is a set that you can directly populate with item instances for a bar. Use this option when your items are lightweight enough to stay in memory for the duration of your app’s lifetime, and when they don’t contain state that might change over time.
NSTouchprotocol, and its
touchdelegate method, give your app a way to create items on-demand. Use this option when it makes more sense in terms of resource usage and reflecting dynamic state.
Bar(_: make Item For Identifier:)
Whichever of these two approaches you employ, the system is in charge of populating a bar’s private items array based on three things:
Your configuration of the bar’s item-identifiers properties, as explained in NSTouchBar Customization
Any nesting you have specified, as explained in NSTouchBar Composition and Nesting
Any customization that the user has specified for the bar
As your app runs, you can obtain the identifiers of the items eligible for presentation in a bar—specifically, those in its private items array—by accessing the read-only
item property. This property reflects the current state of the bar instance, including any customization that has been performed by the user and any dynamic composition that has been performed by the system.
AppKit provides a rich Touch Bar customization facility for users that appears, upon user request, on the main display. Make your bars customizable unless you have a specific UI need not to do so.
A customizable bar automatically obtains onscreen UI which lets the user:
Change which items are part of the shown bar
Rearrange items within the shown bar
A user invokes the onscreen customization UI by choosing a dedicated menu item, as described in The Customization Menu Item.
To make an
NSTouch object eligible for customization, assign it a globally-unique
customization identifier. For the identifier string, use reverse-DNS style, such as “
Next, specify the bar’s items and customization possibilities by populating its item identifier lists. Each such list is an array, each of whose elements is the identifier (of type
NSTouch) for an item (an
NSTouch object). A bar’s item identifier lists are:
Default item identifiers, specified in a bar’s
default property. Always specify this property for an
NSTouch object, even if you elect to make the bar noncustomizable. The system:
Shows this list’s items by default when the system displays the bar.
Includes a preconfigured bar representation, containing these items, in the associated customization UI (when you have designated the bar as customizable by assigning it a
customizationproperty value); the user can drag the default bar into the Touch Bar, should they want to return to the default configuration.
Additional item identifiers, specified in a bar’s
customization property. Always configure this property for a customizable bar. The system uses this list by showing representations of its items individually in the customization UI, arranged in the same order as you specify in the property array. When there is available geometric space, a user can drag in to the active bar any of the items in this list. If there is not enough space, a dragged item replaces the item or items under the spot the new item is dropped.
Required item identifiers, specified in a bar’s
customization property. Configure this property at your discretion, depending on the design of your app. The user cannot remove from the bar any of the items you specify in this list.
To provide textual labels in the customization UI, use the
customization property on each
NSTouch instance you include in a customizable bar. The accessibility system in macOS also makes use of these labels.
If your app design requires a noncustomizable
Group Item, Popover Item, and Composed Bar Customization
AppKit lets you specify any bar as customizable or not. The customization configuration you provide for a bar remains associated with the bar and its items—even when those items are nested by the system into another bar higher in the responder chain. See NSTouchBar Composition and Nesting for details about bar composition in the responder chain.
The system also respects your bar customization configuration when you use group and popover items. Each of these item types itself contains one or more bars—which can, in turn contain group items and popover items, and so on. The rest of this section explains how customization works for the bars containing, and bars within, group items and popover items.
A group item (an instance of the
NSGroup class) has one bar, held in the object’s
group property. AppKit supports nesting of group items, in that you can configure a
group bar to itself contain one or more group items (or, for that matter, items of any other type, guided by what works well in your app).Here are some examples of how customization for group items works in practice:
If you configure a bar as customizable, and give it a group item whose bar you configure as not customizable, then the array of items in the
groupbar appears in the customization UI as an atomic unit. During customization, a user can manipulate the array of items, but strictly as a unit: If the (noncustomizable)
groupbar is visible in the Touch Bar, the user can remove it as a unit, or can rearrange it among the other items in the
groupbar; if the
groupbar is instead visible in the customization UI, the user can add it back to the Touch Bar, as a unit, placing it within the bar that owns the group item.
If you configure a bar as not customizable, and give it a group item whose bar you configure as customizable, then the
groupbar’s items appear in the customization UI as individual items. During customization, a user can manipulate each item separately: If an item from the
groupbar is visible in the Touch Bar, the user can remove it or can rearrange its position individually among the other items in the
groupbar; if an item from the
groupbar is instead visible in the customization UI, the user can add it back to the Touch Bar, individually, placing it anywhere within the
groupbar that owns it.
A popover item (an instance of the
NSPopover class) has two bars: one bar you specify in its
popover property and a second, optional bar you can specify in its
press property. Here are some examples of how customization for popover items works in practice:
If you configure a bar as customizable, and give it a popover item whose
popoverbar you configure as not customizable, the
popoverbar never appears in the customization UI. If the user invokes the customization UI when the (noncustomizable) popover item itself (not the button’s associated
popoverbar) is visible in the Touch Bar, the customization UI lets the user rearrange the position of the popover item relative to the other items in the containing bar. If, on the other hand, the user invokes the customization UI when the (noncustomizable)
popoverbar is visible in the Touch Bar, the system dismisses the popover bar and shows, in the customization UI, customization options for the bar that contains the popover item.
If you configure a
popoverbar as customizable, the user can invoke the
popoverbar (by tapping the popover item that owns it, in the Touch Bar) and then use the customization UI to manipulate the items in the
The Customization Menu Item
A user invokes the customization UI for a particular
NSTouch object, when it is visible in the Touch Bar, by choosing the bar customization menu item. To enable this menu item you must explicitly opt-in, which you can do in the following ways:
If you want the system to automatically name, place, validate, and activate this menu item in your app’s menus, set the
isproperty of your app object (of type
Automatic Customize Touch Bar Menu Item Enabled
To explicitly place the customization menu item in one of your app’s menus, employ the
togglemethod of your app object. When you do this, the system still names and validates the menu item, and hides it on systems that do not have a Touch Bar.
Touch Bar Customization Palette(_:)
If you attempt to employ the customization menu item (using either of these two approaches), but do not provide a customization identifier property (
customization) for a bar, the customization menu item appears when that bar is active—but the menu item, in this case, is disabled.
If your app attempts to use both automatic and explicit placement of the customization menu item, the system respects your explicit control and does not place the item automatically.
The user controls the width of the Control Strip and can choose to hide it, and the system is in charge of the nesting of
NSTouch instances (for the bars you make eligible for composition). As a result, the available display width for your bars can vary. There is no API for you to obtain the current available display width.
In your layout design, do not depend on a particular Control Strip size. Do anticipate dynamic composition and nesting for your bars.
If you need more horizontal space than might be available, use a popover item, a scrubber, or a scroll view—as they fit your design needs, but in that, descending, order of preference.
In geometric-space-constrained scenarios, the system hides
NSTouch instances according to their visibility priority. Read "NSTouchBarItem priority for visibility” in NSTouchBarItem Configuration.
If you need to center an item in the Touch Bar, designate it as a principal item by assigning it to its bar’s
principal property. Do not hard-code spacing in an attempt to ensure an item is centered. If you want a group of items to appear centered in the Touch Bar, designate the group item (of type
NSGroup) as the principal item.
NSTouchBar Composition and Nesting
You can configure a bar to support dynamic composition, in which the system shows the bar in an expanded form that contains items from bars lower in the responder chain (that is, closer to the first responder).
To allow a bar to serve as a container for nesting, add the
other item identifier to the bar’s
default array. A bar that includes this identifier, and that is relatively higher in the responder chain, can then (at runtime) include the items from an eligible bar relatively lower in the responder chain.
The position that you specify for the other-items proxy, within a bar’s
default array, tells the system where you want nested items to be placed.
The system determines whether or not to compose bars in this way, based on system policy and available geometric space in the Touch Bar.
NSTouch object nesting can be chained, according to available geometric space in the Touch Bar. For example, a view and a text field within that view could each contribute their items to the bar defined for a parent window controller.
When the system nests one bar’s items into another bar higher in the responder chain, the items appear to the user, in the Touch Bar, as fully incorporated into the higher bar. There is no visual boundary or additional spacing to distinguish the items as being nested.
If a bar does not employ the
other identifier, the system hides that bar when another bar, lower in the responder chain, is eligible for display.
When determining which items to show in the Touch Bar for the current first responder, the system traverses up the entire responder chain. This lets the system accommodate any proxy items in bars defined for objects higher in the chain, thereby respecting the fact that any bar, defined for an object at any position in the responder chain, might include the other-items-proxy identifier.
Customization for Composed Bars
The logical, geometric boundary for a nested
NSTouch object is not visible to the user in the Touch Bar. However, the boundary remains in effect in terms of customization. A user cannot rearrange a nested bar’s items outside of its boundary.
For example (and employing ASCII-art here) say you have a bar, higher in the responder chain, configured like this:
And say you also have a bar, lower in the responder chain, eligible for display in the Touch Bar according to the system and the current app state, configured like this:
The composed bar would correspond to this arrangement in the Touch Bar:
With the customization UI, the user could then rearrange the items represented here by
(C), but only as long as those items remained contiguous during the rearrangement, thereby respecting the logical boundary of the bar that defines them.
Item Spacing for Composed Bars
When the system nests
NSTouch objects that include spacing items, it merges any resulting adjacent spacing. Ensure that your bars appear as you expect them to, testing on the versions of macOS that you support. For more on spacing items, see Other Common NSTouchBarItem Types.
NSTouchBar Discovery and the Responder Chain
At runtime, the system traverses up the responder chain, starting at the object with focus, to discover objects that conform to the
NSTouch protocol. Such objects are called bar providers. The system then populates the Touch Bar, potentially with multiple, nested bars, according to system policy and available geometric space.
Specifically, bar discovery by the system proceeds as shown from bottom-to-top in this list:
10. App delegate
9. App object
8. Main window’s controller
7. Main window’s delegate
6. Main window
5. Main window’s first responder
4. Key window’s controller
3. Key window’s delegate
2. Key window
1. Key window’s first responder
When the system encounters a bar provider that is an instance of an
NSResponder subclass, the system then additionally searches up the responder chain anchored at that object.
For example, in a complicated but otherwise standard app, bar discovery might look like this—again, traversed bottom-to-top:
9. App delegate
8. App object
7. Key window’s controller
6. Key window
5. View controller that is closest to root of window
4. View that is closest to root of window
3. Intermediate view controllers and views
2. View controller of key window’s first responder
1. Key window’s first responder
The Touch Bar can show one bar nested within another, as described in NSTouchBar Composition and Nesting.
Accessibility and the Touch Bar
AppKit views and controls adopt the
NSAccessibility protocol and automatically send appropriate accessibility notifications. Because the Touch Bar is designed to work with AppKit, it is fully accessible.
Be sure to use the customizationLabel property on every
NSTouch instance that you designate as customizable (as described in NSTouchBar Customization). The accessibility system in macOS makes use of these labels.
To learn more about accessibility, read Accessibility Programming Guide for OS X.
AppKit Support for the Touch Bar
To support the Touch Bar feature, AppKit provides several enhancements, first available in macOS 10.12.1:
Gesture recognizer support.
You can use the
NSMagnificationclass in bar items. To enable two-finger pinch gestures, set the recognizer’s
allowedmask property, on the gesture recognizer, to the
NSTouchconstant from the
.Touch Type .direct
.Touch Type Mask
NSGestureabstract class is enhanced with a set of methods that let you implement responses to touch events:
NSPressconcrete classes are each enhanced with a
numberproperty to let you specify the number of touches required for a gesture match.
Of Touches Required
Touch type changes. To enable touch events in a custom view, you must set the value of a view’s
allowedproperty to a value of
direct. (In macOS 10.12.1, the
acceptsproperty is deprecated in favor of the new
Control appearance support. The
NSSliderclasses are each enhanced with appearance support properties:
selectedfor segmented controls, and
Segment Bezel Color
trackfor sliders. (With the Touch Bar, you employ sliders indirectly, as used by slider items.)
Convenience initializers. Starting in macOS 10.12, you can use a rich set of convenience initializers for controls. These initializers simplify the definition of bar items and take care of appearance and sizing for the Touch Bar. In particular, the
NSSliderclasses now offer a variety of convenience initializers such as
image: target: action:)
Text support. Methods and properties in the
NSTextclasses, and in the
NSTextprotocols, support using the Touch Bar for spell checking, predictive text suggestion, text completion, and automatic handling of trailing space. For example:
When you use an
NSTextobject, you gain automatic Touch Bar support for text styling and predictive text suggestions.
When you use an
NSCandidateobject, you can use the
List Touch Bar Item
requestmethod. This method provides a completion handler that you can use to filter or otherwise manage the candidate text.
Candidates(for Selected Range: in: types: options: in Spell Document With Tag: completion Handler:)
New template images. AppKit adds many new template images for you to use in your
NSTouchobjects. A few examples of these images are:
Bar Add Template Name
Bar Compose Template Name
Bar Go Back Template Name
touch, and NSImageNameTouchBarHomeTemplate. Always use templates for images in your items: they respond automatically to system white-point changes. Note that these images are exclusively for use in the Touch Bar and not in onscreen windows. For a complete list of these template images, see the overview in the
Bar Go Forward Template Name
Scroll views. If your UI for a popover item needs more horizontal space, you can use a scroll view (an instance of the
NSScrollclass). Do not, in this case, enable the popover item’s press-and-hold option, because doing so interferes with scrolling. For more on using scroll views, read Handling Touch Events in NSTouchBarItem Objects.
Stack views. You can group bar items by using an instance of the
NSStackclass. However, doing so loses system support for spacing. When you instead place items into a group item (an instance of the
NSGroupclass), the system:
Touch Bar Item
Manages inter-item spacing
Supports user customization for the individual items
Development Considerations for the Touch Bar
The Xcode Touch Bar simulator represents the Touch Bar onscreen and supports some user interaction. However, some interactions are unavailable in the simulator. For example, you cannot perform two-finger gestures in the Touch Bar simulator.
If you are adopting Touch Bar support for your app, but running Xcode on a Mac without a Touch Bar, you can enable the Xcode Touch Bar simulator by choosing Window > Show Touch Bar in Xcode.
Interface Builder supports development for the Touch Bar with nib objects available in the object library. Drag and drop bars and items from the object library into your canvas, and then attach them to your app’s responders as desired. For more information, see Xcode Help.
Performance Considerations for the Touch Bar
The Touch Bar’s display and the MacBook screen share resources, including the main CPU and GPU of the MacBook. To ensure that your Touch Bar controls perform well, follow the usual best practice of protecting your app’s main thread from doing too much work. For example, do not perform rendering work for the main display on the main thread.
In addition, pay attention to the relative amounts of time your app spends on updates to the main display relative to updates to the Touch Bar. The optimum ratio can vary according to what the user is doing. For example:
When a user is interacting with the Touch Bar and watching the Touch Bar, such as to control audio, ensure that your app gives priority to updating the Touch Bar.
When a user is instead interacting with the Touch Bar but watching the main display, such as when using a scrubber to browse pages of content, balance your app’s display update work between the Touch Bar and the main display.
Always test Touch Bar performance using the specific MacBook hardware you support. Specifically, do not rely on the Xcode Touch Bar simulator when tuning your app for Touch Bar performance.