You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

SwiftUI开发macOS应用:如何检测Mac是否配备Touch Bar

SwiftUI开发macOS应用:如何检测Mac是否配备Touch Bar

嘿,刚好我前段时间在做自己的macOS SwiftUI应用时,也遇到了一模一样的需求——只支持Apple Silicon,还要根据有没有Touch Bar来做不同的UI展示。给你分享几个实用的方案,都是亲测有效的哈~

一、封装检测逻辑+注入环境变量(推荐)

这种方式可以把检测结果全局注入SwiftUI环境,任何子视图都能直接调用,不用重复写检测代码,非常适合中大型项目。

首先,先写一个简单的结构体封装Touch Bar的检测逻辑,专门针对Apple Silicon Mac优化:

import AppKit
import SwiftUI

// 封装Touch Bar检测逻辑,适配Apple Silicon Mac
struct TouchBarChecker {
    static var isEquipped: Bool {
        // 两个核心条件:系统支持TouchBar,且当前设备实际配备了TouchBar
        NSTouchBar.isAvailable && NSApplication.shared.isTouchBarPresent
    }
}

然后定义一个自定义环境键,把检测结果注入到App的环境中:

// 自定义环境键,用于传递TouchBar存在状态
private struct HasTouchBarKey: EnvironmentKey {
    static let defaultValue: Bool = false
}

// 扩展环境值,让视图可以轻松获取状态
extension EnvironmentValues {
    var hasTouchBar: Bool {
        get { self[HasTouchBarKey.self] }
        set { self[HasTouchBarKey.self] = newValue }
    }
}

// 在你的App结构体里完成环境注入
@main
struct SignDictApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(\.hasTouchBar, TouchBarChecker.isEquipped)
        }
    }
}

接下来在视图里就可以直接通过环境变量获取状态,实现条件UI了:

struct ContentView: View {
    // 从环境中读取TouchBar状态
    @Environment(\.hasTouchBar) private var hasTouchBar
    
    var body: some View {
        VStack(spacing: 20) {
            if hasTouchBar {
                Text("🎯 设备配备Touch Bar,显示专属功能区")
                // 这里放TouchBar专属的UI组件,比如快捷操作按钮组
                HStack {
                    Button("TouchBar快捷翻译") {}
                    Button("TouchBar收藏") {}
                }
            } else {
                Text("🖥️ 设备无Touch Bar,显示替代操作区")
                // 无TouchBar时的替代UI,比如底部工具栏
                ToolbarItem(placement: .bottomBar) {
                    Button("普通操作入口") {}
                }
            }
        }
        .padding()
    }
}

二、直接在视图中检测(适合简单场景)

如果你的项目很小,或者只在一两个视图里用到这个判断,也可以跳过环境注入,直接在视图里调用检测逻辑:

struct SimpleView: View {
    var body: some View {
        VStack {
            if TouchBarChecker.isEquipped {
                Text("有Touch Bar的专属UI")
            } else {
                Text("无Touch Bar的默认UI")
            }
        }
    }
}

三、额外技巧:给TouchBar设置自定义内容

既然要适配TouchBar,顺便提一下SwiftUI里怎么给视图绑定自定义TouchBar内容,结合检测结果使用更灵活:

struct ContentView: View {
    @Environment(\.hasTouchBar) private var hasTouchBar
    
    var body: some View {
        VStack {
            // 主视图核心内容
            Text("SignDict 词典主界面")
        }
        // 只有当设备有TouchBar时,才添加自定义内容
        .touchBar {
            guard hasTouchBar else { return }
            
            NSTouchBar {
                // 自定义TouchBar项目:搜索按钮
                NSCustomTouchBarItem(identifier: .init("searchItem")) {
                    Button(action: {
                        // 执行搜索操作
                    }) {
                        Image(systemName: "magnifyingglass")
                            .frame(width: 30, height: 30)
                    }
                }
                
                // 添加弹性分隔符
                NSTouchBarItem(identifier: .flexibleSpace)
                
                // 自定义TouchBar项目:发音按钮
                NSCustomTouchBarItem(identifier: .init("pronounceItem")) {
                    Button(action: {
                        // 执行发音操作
                    }) {
                        Image(systemName: "speaker.wave.2.fill")
                            .frame(width: 30, height: 30)
                    }
                }
            }
        }
    }
}

最后啰嗦一句:因为你只支持Apple Silicon Mac,完全不用考虑老Intel机型的兼容性问题,上面的API在Big Sur及以上系统(Apple Silicon最低支持版本)都是完全可用的,放心用就行~

火山引擎 最新活动