Touch Bar曾是MacBook Pro上一块颇具争议的OLED屏幕,它取代了传统的功能键区,提供了完全可编程的交互空间。虽然苹果在后续机型中放弃了这个设计,但存量设备依然不少,许多音乐制作、设计类应用的Touch Bar支持依然是加分项。本文将从零开始讲解如何在macOS应用中为Touch Bar添加自定义按钮、滑块以及交互式弹出视图,内容基于AppKit的NSTouchBar体系,同时也会提到SwiftUI的封装方式。

一、Touch Bar的架构与基本原理
Touch Bar的核心类是NSTouchBar,它本质上是一个容器,里面摆放着若干NSTouchBarItem对象。每个item占据Touch Bar上的一块区域,可以是按钮、滑块、颜色选择器、字符候选等各种控件。系统在响应者链(Responder Chain)中寻找实现了makeTouchBar()方法的对象,拿到它返回的NSTouchBar实例后渲染到触控栏上。
这一点和菜单、工具栏类似:都是通过响应者链按需提供内容。当你的窗口中First Responder发生变化时,Touch Bar的内容也会随之切换。例如光标从文本框移动到画布区域时,可以让Touch Bar展示完全不同的控件组合,这正是Touch Bar设计的精妙之处。
系统预置了许多item类型,常用的包括NSCustomTouchBarItem(放任意NSView)、NSButtonTouchBarItem(按钮)、NSSliderTouchBarItem(滑块)、NSPopoverTouchBarItem(弹出视图)、NSSharingServicePickerTouchBarItem(分享按钮)以及NSCandidateListItem(文字候选)。系统控件自带标准的间距、圆角和按压反馈,优先使用它们能保证视觉一致性。
二、创建自定义按钮与滑块
先从最基础的场景开始:在视图控制器中重写makeTouchBar()方法,创建一个包含两个按钮的Touch Bar。每个item需要一个唯一标识符,这些标识符要在touchBar(_:makeItemForIdentifier:)回调中实例化,系统会根据布局策略惰性创建item。
class CanvasViewController: NSViewController {
override func makeTouchBar() -> NSTouchBar? {
let touchBar = NSTouchBar()
touchBar.delegate = self
touchBar.defaultItemIdentifiers = [
.init("com.demo.clearButton"),
.init("com.demo.brushSlider")
]
return touchBar
}
}
extension CanvasViewController: NSTouchBarDelegate {
func touchBar(_ touchBar: NSTouchBar,
makeItemForIdentifier identifier: NSTouchBarItem.Identifier) -> NSTouchBarItem? {
switch identifier.rawValue {
// 自定义按钮
case "com.demo.clearButton":
let item = NSButtonTouchBarItem(
identifier: identifier,
title: "清空画布",
target: self,
action: #selector(clearCanvas)
)
item.bezelColor = NSColor.systemRed
return item
// 滑块
case "com.demo.brushSlider":
let item = NSSliderTouchBarItem(identifier: identifier)
item.label = "笔刷大小"
item.minimumValue = 1
item.maximumValue = 100
item.value = 20
item.target = self
item.action = #selector(brushSizeChanged(_:))
return item
default:
return nil
}
}
@objc func clearCanvas() {
print("清空画布")
}
@objc func brushSizeChanged(_ sender: NSSliderTouchBarItem) {
print("当前笔刷大小:\(sender.value)")
}
}上面的代码有两个细节值得注意。第一,item的标识符建议使用反向域名的格式,避免和系统标识符冲突。第二,defaultItemIdentifiers决定了item的排列顺序,你可以随时通过修改这个数组动态增删item,系统会带动画地刷新Touch Bar内容。
按钮的外观可以通过bezelColor设置背景色,通过image替换文字为图标。滑块item则支持设置label显示在左侧的文字标签,设置value的初始值后系统会渲染成带预览宽度的样式,非常适合调节音量、透明度这类连续值参数。
三、交互式弹出视图:NSPopoverTouchBarItem
Touch Bar的空间有限,当控件较多时需要用到弹出视图。NSPopoverTouchBarItem会在点击时将整个Touch Bar区域(右侧系统控制区除外)替换为自定义内容,并带一个塌陷按钮让用户返回。它可以设置collapsedRepresentation作为折叠态的入口,通常是按钮或图标。
case "com.demo.colorPopover":
let popover = NSPopoverTouchBarItem(identifier: identifier)
popover.collapsedRepresentationLabel = "颜色"
let colorPicker = NSColorPickerTouchBarItem(
identifier: .init("com.demo.innerColorPicker")
)
colorPicker.target = self
colorPicker.action = #selector(colorPicked(_:))
colorPicker.color = NSColor.red
popover.popoverTouchBar = NSTouchBar()
popover.popoverTouchBar?.defaultItemIdentifiers = [colorPicker.identifier]
popover.popoverTouchBar?.delegate = self
return popover这段代码演示了嵌套结构:外层Touch Bar放一个弹出item,展开后显示内层的颜色选择器。事实上popoverTouchBar属性本身又是一个NSTouchBar,所以你可以无限嵌套弹出视图,实现多级菜单式的交互。不过从用户体验出发,层级最好控制在两层以内,否则在这么窄的屏幕上找返回按钮会比较痛苦。
如果你的弹出内容是自定义视图,可以改用NSCustomTouchBarItem作为弹出内容的载体,把任意NSView塞进去。比如一个包含多个色块的NSStackView,点击色块后手动调用dismissPopover收回弹出视图。
四、SwiftUI方式与调试技巧
如果项目已经基于SwiftUI,可以用.touchBar修饰符省去delegate样板代码。SwiftUI提供了TouchBarItem、TouchBarSlider等跨平台类型(实际在macOS上生效),写法如下:
struct ContentView: View {
@State private var brushSize: Double = 20
var body: some View {
CanvasView()
.touchBar {
TouchBarItem(id: "clear") {
Button("清空画布") { print("清空") }
}
TouchBarSlider(value: $brushSize, label: "笔刷") {
Image(systemName: "paintbrush")
}
}
}
}SwiftUI的方式明显更简洁,绑定状态即可驱动UI更新。不过它的能力不如AppKit完整,比如自定义弹出视图的内层布局、精细控制bezel颜色等场景还是需要退回NSCustomTouchBarItem桥接NSView来处理。
调试方面有几点经验:首先,模拟器不显示Touch Bar,必须在真机上测试;其次,可以在Xcode的Debug菜单中找到View Touch Bar Simulator选项,唤出一个虚拟Touch Bar窗口方便调试(需要设备支持);最后,如果你的makeTouchBar()没有被调用,多半是窗口的第一响应者链没有走到你的控制器,可以检查一下视图层级中的nextResponder是否正确串联。另外别忘了在Info.plist中无需额外声明权限,但应用必须运行在前台才会获得Touch Bar的控制权,后台应用是被系统自动排除的。
总的来说,Touch Bar开发的核心就是NSTouchBar容器的组装和item的按需创建,掌握了按钮、滑块、弹出视图这三类常用item,就能覆盖绝大多数自定义场景。即便这个硬件已经停产,理解这套响应者链驱动的UI机制,对理解macOS整体的设计哲学也很有帮助。
Touch Bar开发macOS NSTouchBarSwiftUI触控栏修改时间:2026-09-15 15:24:47