ByteNoteByteNote
Permiso:macOS 权限授权从 7 步降到 2 步
字

字节笔记本

2026年10月5日 · 约 8 分钟读完

Permiso:macOS 权限授权从 7 步降到 2 步

API中转
¥120

macOS 的隐私权限授权一直有个出了名的体验问题:当应用需要辅助功能、屏幕录制这类敏感权限时,传统做法是让用户点「打开系统设置」,在侧栏里找到对应面板,在一长串列表里定位自己的应用,点「+」号,再到文件选择器里把应用添加进来,最后手动打开开关。七八步走完,相当一部分用户早已中途放弃。

OpenAI 的 AI Agent 编程工具 Codex 给出了一个被广泛称赞的解法:直接在系统设置的权限列表下方覆盖一个拖拽区域,用户把应用图标拖进去,授权就完成了。随后,这套交互被开源成了 Swift 包 Permiso,任何 macOS 应用都可以一行代码接入,目前在 GitHub 上已收获 500 多个 star。

Codex 的拖拽授权界面:权限列表下方覆盖一个拖拽区域

Permiso 是什么

Permiso(仓库地址 zats/permiso)是一个极简的 Swift 包:全部实现只有 6 个源文件、合计 687 行代码,复刻的正是 Codex 那个「拖拽授权」交互。通过 Swift Package Manager 引入仓库后,一行代码就能在应用里弹出权限引导覆盖层:

swift
import Permiso

@MainActor
func showAccessibilityHelper() {
    PermisoAssistant.shared.present(panel: .accessibility)
}

调用之后,用户看到的是:

  1. 系统设置自动打开,并跳到对应的权限面板;
  2. 权限列表正下方出现一个拖拽区域;
  3. 把应用图标拖进列表,授权完成。

而不再是传统那条「系统设置、隐私、辅助功能、找应用、点加号、添加、开启」的漫长路径。

技术原理:六个文件怎么协作

整条链路的实现非常克制,核心流程如下图:

Permiso 权限引导核心流程

六个源文件各司其职:

文件行数职责
PermisoAssistant.swift85入口,负责 present 与 dismiss、定时器追踪
OverlayWindowController.swift315透明覆盖窗口的创建、定位与渲染
AppDragSourceView.swift136可拖拽的应用图标视图
SettingsWindowLocator.swift105在屏幕上定位系统设置窗口的位置和大小
PermisoPanel.swift23定义权限面板类型与直达 URL
PermisoHostApp.swift23描述「哪个应用需要授权」

有三个实现细节值得展开。

第一,窗口位置追踪。系统设置窗口可以被用户随意移动和调整大小,Permiso 用一个 0.15 秒间隔的定时器不断重新定位覆盖层,保证它始终贴在权限列表下方。定位依据来自 SettingsWindowLocator 对最前台窗口的快照,一旦找不到系统设置窗口,覆盖层会直接隐藏。

第二,应用切换监听。Permiso 向 NSWorkspace 的通知中心注册了 didActivateApplicationNotification,用户切走应用时立即刷新位置或隐藏覆盖层,不会留下一个悬在半空的孤儿窗口。

第三,拖拽源视图。AppDragSourceView 基于 NSDraggingItem 和 beginDraggingSession 这套原生拖放 API 实现,覆盖层里的应用图标可以被直接拖进系统设置的列表。覆盖窗口本身的 level 被设为 .statusBar,这也是它能盖在系统设置窗口上面的关键。

从 7 步到 2 步:设计为什么被称赞

把两条路径并排看,差距一目了然:

传统 7 步流程与 Permiso 2 步流程对比

传统流程里,用户要经历提示、跳转、找面板、找应用、点加号、文件选择器、开启开关这七步,多数人卡在「列表里找不到自己的应用」和「不知道加号在哪」这两处。Permiso 把它压缩成两步:覆盖层弹出、拖进图标。有开发者在相关讨论里点评:「2026 年的好设计,是让平台故意设阻的事变得简单。」macOS 的权限链路偏长,某种程度上是安全上的有意为之,而覆盖层方案在不绕过任何安全机制的前提下,把复杂性留给了开发者,把简单留给了用户。

支持哪些权限

PermisoPanel 枚举目前提供两个面板:

swift
public enum PermisoPanel: String, CaseIterable, Sendable {
    case accessibility = "Privacy_Accessibility"
    case screenRecording = "Privacy_ScreenCapture"
}

这两个恰好是 macOS 开发者最常打交道的权限:全局快捷键、模拟点击需要辅助功能,截屏录屏类工具需要屏幕录制。每个面板各自维护一个 x-apple.systempreferences: 协议的直达 URL,present 时由系统直接跳到对应面板,省去用户翻找的过程。输入监控等更多面板类型目前源码里还没有,需要的话可以照着现有实现自行扩展。

怎么集成

通过 Swift Package Manager 添加仓库地址即可引入,使用时按需选择面板:

swift
import Permiso

// 需要辅助功能权限时
PermisoAssistant.shared.present(panel: .accessibility)

// 需要屏幕录制权限时
PermisoAssistant.shared.present(panel: .screenRecording)

拖拽区里展示的应用信息由 PermisoHostApp 描述,包含名称、bundleURL 和图标,默认通过 PermisoHostApp.current() 从主 bundle 自动读取,一般不需要手动配置。

一个通用的 macOS 模式:透明覆盖层

Permiso 依赖的核心技术,即用一个透明 NSWindow 盖在其他应用上面,是 macOS 原生开发里相当通用的模式。社区里可以找到不少同类实践:有的项目把覆盖层贴在刘海区展示 Agent 状态,有的盖在桌面上做截图标注,有的用来显示录音状态。Permiso 的价值在于,它把这个模式用在一个非常具体的痛点上,并且只用了不到 700 行代码,是一份很适合拿来精读的实现样本。

小结

Permiso 是 Codex 权限引导流的开源 Swift 实现:6 个源文件、687 行代码、一行 API,把 macOS 权限授权从 7 步压到 2 步。如果你的 macOS 应用需要辅助功能或屏幕录制权限,或者你想学习「覆盖层、窗口追踪、拖放」这套组合拳,它都值得一看。

有开发者的那句点评,可以作为这篇的注脚:「2026 年的好设计,是让平台故意设阻的事变得简单。」

本文基于 Permiso 仓库源码与相关公开讨论整理,仓库地址:https://github.com/zats/permiso

相关文章

分享: