导读:本期聚焦于韦伯创作的《macOS Touch Bar开发:如何为MacBook Pro自定义触控栏按钮、滑块与交互式弹出视图?》,敬请观看详情。Touch Bar是MacBook Pro顶部那条可自定义的OLED触控条,虽然苹果后续机型已经取消了这个设计,但在大量存量设备上它依然可以玩出很多花样。本文将带你系统了解如何使用NSTouchBar和NSTouchBarItem在macOS应用中创建自定义按钮、滑块以及交互式弹出视图,并顺带介绍SwiftUI对Touch Bar的封装支持。内容涵盖Touch Bar的基础架构、常用控件类型、delegate与delegate item的注册流程、弹窗与滚动区域的实现方式,以及调试和适配中的常见坑点,帮助你快速上手触控栏开发。

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

macOS Touch Bar开发:如何为MacBook Pro自定义触控栏按钮、滑块与交互式弹出视图?

一、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提供了TouchBarItemTouchBarSlider等跨平台类型(实际在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

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260915/57356.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。