如何使用Swift代码在Mac OS应用中编程实现打开屏幕键盘功能
问题原因
- MacOS 11(Big Sur)及以上版本对沙盒应用的跨进程调用做了严格限制,你遇到的
System Preferences isn’t running报错本质是缺少Apple事件发送权限,同时脚本没有做系统偏好设置的预启动判断。 - 你已添加的两个entitlement仅声明了键盘偏好设置域的访问权限,没有授予应用向系统偏好设置发送控制指令的权限。Script Editor本身默认拥有系统级应用的调用权限,所以单独运行脚本可以正常生效,放到自建沙盒应用中就会触发权限拦截。
解决方案
方案一:补全权限+调整AppleScript逻辑
1. 补充Entitlement配置
在项目的entitlements文件中新增如下配置:
<!-- 申请Apple事件基础发送权限 --> <key>com.apple.security.automation.apple-events</key> <true/> <!-- 针对系统偏好设置、屏幕键盘进程的临时例外权限 --> <key>com.apple.security.temporary-exception.apple-events</key> <array> <string>com.apple.systempreferences</string> <string>com.apple.KeyboardViewer</string> </array>
2. 调整AppleScript脚本,增加预启动逻辑
-- 先判断并启动系统偏好设置,避免未运行报错 tell application "System Preferences" if not running then launch delay 0.3 reveal pane id "com.apple.preference.keyboard" reveal anchor "InputSources" of pane id "com.apple.preference.keyboard" end tell -- 勾选菜单栏输入项显示(如果未开启的话) tell application "System Events" to tell process "System Preferences" click checkbox "Show Input menu in menu bar" of window 1 end tell tell application "System Preferences" to quit -- 启动屏幕键盘 tell application "Keyboard Viewer" to launch
3. Swift调用示例
import Foundation func openScreenKeyboard() { let scriptSource = """ 上面调整完成的AppleScript脚本内容 """ var error: NSDictionary? guard let script = NSAppleScript(source: scriptSource) else { return } script.executeAndReturnError(&error) if let err = error { print("调用失败:\(err)") } }
注意:第一次调用时系统会弹出权限申请弹窗,需要用户允许你的应用控制系统偏好设置,可在应用内提前做权限引导。
方案二:直接启动屏幕键盘应用(更简单,无需AppleScript)
你可以直接通过NSWorkspace调用系统内置的屏幕键盘应用,不需要复杂的权限配置,适配性更强:
import AppKit func openScreenKeyboard() { let kbViewerPath = "/System/Library/Input Methods/KeyboardViewer.app" NSWorkspace.shared.open(URL(fileURLWithPath: kbViewerPath)) }
内容的提问来源于stack exchange,提问作者mahmoud
相关产品推荐
相关产品推荐

