macOS 评估体验的新动向
What’s new in assessment on macOS
2026年6月10日
一句话判断
✅ macOS 的考试模式(Assessment Mode)终于从“粗暴锁死全屏”进化到了“系统级精细化管控”,教育类 App 不用再自己写脆弱的防作弊拦截代码了。
这场 Session 讲了什么
以前在 Mac 上做考试 App,防作弊简直是噩梦。你得自己写一堆 CGEventTap 拦截快捷键,用无边框窗口死死遮住 Dock 和 Menu Bar,结果 macOS 一更新,你的拦截代码就失效了,学生随便切个输入法就能把答案发出去。
现在 macOS 27 把 Automatic Assessment Configuration(自动评估配置,简称 AAC)框架彻底重做了。Apple 直接把系统底层的 UI 和进程管控权限开放给了开发者。你可以通过 API 精确告诉系统:“保留 Dock 但只显示考试 App”、“隐藏听写和自动填充”、“只允许显示电量和音量的 Menu Bar 图标”。
这对做教育、在线认证考试的团队是巨大利好。把防作弊和系统环境配置直接甩给 OS 层,App 终于可以专注做题和音视频监控的业务逻辑了。
值得深挖的点
把 Mac 变回 Mac:系统 UI 的白名单机制
Mac 不是 iPad,用户早就习惯了 Menu Bar 和 Dock。以前的考试软件为了防作弊,喜欢搞一个全屏无边框窗口把系统 UI 全挡死,这不仅让学生容易迷失,还会引发幽闭恐惧症般的焦虑。
Apple 这次的设计选择非常聪明:不搞一刀切,而是给了一套白名单 API。你可以通过 allowedMenuBarItems 精确控制右上角能显示什么,通过 allowsDock 让 Dock 保持显示但只渲染白名单里的 App。这种做法的 Trade-off 是,开发者需要仔细梳理哪些系统组件是“安全且必要”的。好处是原生渲染,不用自己画假 UI;坑在于,如果你白名单配得太抠门,学生可能连调整音量或查看网络状态的入口都没有,遇到断网直接抓瞎。
辅助功能(Accessibility)的范式反转:从“白名单”到“黑名单”
这场 Session 最让我触动的是 Apple 对辅助功能的强硬态度。很多考试软件为了绝对安全,会一刀切关掉 VoiceOver 或 Switch Control(开关控制),这直接剥夺了残障学生考试的权利。
在 AAC 框架里,Apple 强推了一种范式反转:默认保留学生已经开启的辅助功能,开发者需要显式去 限制 那些可能用来作弊的功能(比如会朗读屏幕内容的),而不是去 允许。代码里写 allowsAccessibilitySwitchControl = true 并不会主动帮学生开启它,只是“不阻止”学生自己开启。这逼迫开发者把无障碍当成考试的基建,而不是考完试再打的补丁。
代码片段
1. 考前设备“体检”
场景:在考试开始前,确保学生的 Mac 没有被越狱、魔改,或者开启了会干扰网络监控的隐私功能。
import AutomaticAssessmentConfiguration
func makePreconditionConfig() -> AEAssessmentConfiguration {
let config = AEAssessmentConfiguration()
// 必须开启系统完整性保护,防止底层被篡改
config.requiresSIP = true
// 必须是 MDM 托管设备,且只有一个标准账户登录
config.requiresManagedDevice = true
config.requiresSingleUser = true
config.requiresUserAccountType = .standard
// 强制关闭 lockdown mode 和 iCloud 专用代理,防止网络层拦截考试监控
config.allowLockdownMode = false
config.allowPrivateRelay = false
return config
}
坑:requiresManagedDevice 会直接卡死所有个人设备的考生,如果你的考试允许 BYOD(自带设备),千万别加这条。
2. 手术刀级别的系统 UI 定制
场景:允许学生看到 Menu Bar 调整音量和看时间,但屏蔽掉 Spotlight 和 Siri 防止搜答案。
import AutomaticAssessmentConfiguration
func customizeSystemUI() -> AEAssessmentConfiguration {
let config = AEAssessmentConfiguration()
// 允许显示 Menu Bar,但只保留白名单图标
config.allowsMenuBar = true
config.allowedMenuBarItems = [.battery, .clock, .volume]
// Apple 菜单只保留“睡眠”,防止学生点“关于本机”或“系统设置”
config.allowedAppleMenuItems = [.sleep]
// 允许显示 Dock,但系统会自动过滤,只显示考试允许的 App
config.allowsDock = true
return config
}
坑:allowedMenuBarItems 只是维持现状,如果学生的 Menu Bar 里本来就没加时钟,你加了白名单它也不会凭空出现。
3. 封杀自动化脚本与后台进程
场景:防止学生用 Shortcuts(快捷指令)或 Automator 在后台自动抓取屏幕或模拟点击。
import AutomaticAssessmentConfiguration
func lockDownProcesses() -> AEAssessmentConfiguration {
let config = AEAssessmentConfiguration()
// 考试开始时,系统会自动杀掉所有非白名单的后台进程
config.allowOnlyParticipantsToRun = true
// 彻底禁用 Shortcuts 和 Automator 脚本执行
config.allowsUserScriptExecution = false
// 禁用听写和自动填充,防止系统“好心”帮学生补全答案
config.allowsDictation = false
config.allowsAutoFill = false
return config
}
坑:开启 allowOnlyParticipantsToRun 后,如果你没把考试必需的第三方组件(比如特定的防作弊摄像头插件)加到参与者白名单里,它们会被系统无情秒杀。
最佳实践
- 已有项目的迁移策略:赶紧删掉你项目里那些用
CGEventTap拦截键盘鼠标、用隐藏窗口遮挡 Dock 的“祖传代码”。把这些逻辑全部替换成AEAssessmentConfiguration。自己造的轮子不仅容易在 macOS 大版本更新时崩溃,还会被系统判定为恶意行为。 - 新项目的采用建议:遵循“最小限制原则”。别一上来就把所有
allows...都设为false。先跑通一个宽松的版本,再根据实际作弊手段慢慢收紧权限。过度限制会导致考生的设备出现各种诡异的系统级 Bug。 - 实战中容易踩的坑:一定要注册 Session 转换的回调(Session transition callbacks)。考试结束或意外中断时,系统会退出 Assessment Mode,你的 App 必须在这个回调里清理状态,而不是等 App 被系统强杀。
还有什么值得关注
- 文件系统沙盒化:通过
allowedDirectoriesAndFiles可以限制 Finder 和 Save Panel,让学生只能把考试草稿保存到特定的Documents子目录,碰不到桌面和其他文件。 - 输入法限制:新增了对
allowsStructuralInput(结构性输入)和allowsEmojiKeyboard(表情符号键盘)的控制,防止学生通过拆字或表情包传递暗号。 - 辅助功能细粒度控制:现在可以单独控制 Live Speech(实时语音)和 Background Sounds(背景音),在保障听障/认知障碍学生体验的同时,堵住语音作弊的漏洞。