mcpField
S
swiftui-patterns

swiftui-patterns

github.com/openai开发7.7k61 次安装3 周前更新
代码仓库

关于 swiftui-patterns

面向 macOS SwiftUI 开发者的技能,覆盖场景选择、界面结构、状态管理和桌面交互模式,并提供新应用的组织建议。

主要功能

  1. 01选择合适的 SwiftUI 场景
  2. 02规划状态归属与文件结构
  3. 03构建侧边栏、分栏和检查器布局
  4. 04组织菜单、工具栏与快捷键
  5. 05遵循 macOS 桌面交互模式

适用场景

  1. 01为新 macOS 应用规划场景与目录
  2. 02为现有界面设计侧边栏和详情布局
  3. 03管理窗口状态与用户偏好
  4. 04为重要操作添加菜单和键盘快捷键

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/openai/plugins --skill swiftui-patterns

安装后在 Claude Code 中输入/swiftui-patterns确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

agents/
openai.yaml
references/
commands-menus.md
components-index.md
menu-bar-extra.md
settings.md
split-inspectors.md
windowing.md

详细介绍

SwiftUI 模式

快速开始

根据你的目标选择一条路径:

现有项目
  • 确定功能或场景,以及主要交互模式:文档、编辑器、侧边栏-详情、实用工具窗口、设置或菜单栏附加项。
  • 在设计新的桌面结构前,先阅读最接近的现有场景或根视图。
  • 从 references/components-index.md 中选择相关参考。
  • 如果 SwiftUI 无法简洁地实现所需的平台行为,请使用 appkit-interop 技能,而不要勉强采用不可靠的变通方案。
新应用脚手架
  • 首先选择场景模型:WindowGroup、Window、Settings、MenuBarExtra 或 DocumentGroup。
  • 如果应用同时包含普通主窗口和 MenuBarExtra,且主窗口应在启动时显示,请将 WindowGroup(..., id:) 用于主窗口。对于辅助窗口或按需显示的单例窗口,Window(...) 更合适;在以菜单栏为主的应用中,Window(...) 场景可能不会在启动时自动显示主窗口。
  • 创建脚手架前,使用 git rev-parse --is-inside-work-tree 检查工作区是否已位于 git 仓库中。如果没有,请在项目根目录运行 git init,以便从一开始就能使用 Codex 应用中基于 git 的功能。不要在现有父级检出目录内初始化嵌套仓库。
  • 创建新应用脚手架时,还要在项目本地创建一个 script/build_and_run.sh 和 .codex/environments/environment.toml,以便 Codex 应用的“运行”按钮立即生效。请使用 build-run-debug 及其 references/run-button-bootstrap.md 文件中的确切引导约定,不要在此另行发明一种方案。
  • 编写视图前,先确定哪些状态属于整个应用、场景或窗口。
  • 编写完整 UI 前,先规划文件和模块的边界。对于任何并非简单的小型应用,先创建文件夹结构,并从一开始就按职责拆分文件。
  • 仅在非常简短的一次性示例或代码片段中使用单个 Swift 文件:大致少于 50 行、一个屏幕、没有持久化、没有网络或进程客户端,也没有可复用模型。除此以外,应立即拆分为多个文件。
  • 默认使用适应系统外观的颜色和材质(Color.primary、Color.secondary、语义化前景样式、.regularMaterial 等),让应用自动适配浅色/深色模式。除非用户明确要求固定主题,否则不要将白色或浅色背景写死;默认也不要使用不透明的 windowBackgroundColor 填充根面板。
  • 根据首个功能界面选择参考:窗口管理、命令、分栏布局或设置。

新应用文件结构

对于任何并非简单的 macOS 应用,请从以下结构开始,不要把应用、 所有视图、模型、存储、服务和辅助代码都放在一个 Swift 文件中:

  • App/<AppName>App.swift:仅包含 @main 应用类型和 AppDelegate。
  • Views/ContentView.swift:仅包含根布局和高层组合。
  • Views/SidebarView.swift、Views/DetailView.swift、Views/ComposerView.swift 等:以主要类型命名的功能视图。
  • Models/*.swift:值模型、标识符和选择枚举。
  • Stores/*.swift:持久化和状态存储。
  • Services/*.swift:应用服务端、网络、进程或平台客户端。
  • Support/*.swift:小型格式化器、解析器、扩展和连接辅助代码。

文件应保持精简,并以其中包含的主要类型命名。如果某个文件开始堆积无关的视图、模型、存储、网络客户端和辅助扩展,请先拆分,再添加更多行为。

新应用脚手架的编辑前检查清单

编写完整 UI 前:

  1. 选择场景模型。
  2. 确定状态归属:整个应用、场景、窗口或视图本地。
  3. 规划文件和模块的边界。
  4. 在填充 UI 前创建文件夹结构。
  5. 将 script/build_and_run.sh 和 .codex/environments/environment.toml 与应用源代码分开。

应遵循的一般规则

  • 针对指针、键盘、菜单和多窗口进行设计。
  • 明确划分场景。单独的设置窗口、实用工具窗口或菜单栏额外项应建模为独立场景,而不是塞进一个庞大的 ContentView 中。
  • 优先采用系统桌面交互方式:commands、工具栏、侧边栏、检查器、上下文菜单和 searchable。
  • 对于菜单栏应用,MenuBarExtra 项目标题和操作标签应简短易浏览。可见菜单项文本最多 30 个字符;如果源内容较长,应在呈现前截断或概括,并在专用窗口或详情界面中打开完整内容。
  • 如果 MenuBarExtra 应用仍需像常规 Dock 应用一样运行,并显示主窗口/进程,请通过 @NSApplicationDelegateAdaptor 安装 NSApplicationDelegate,在启动期间调用 NSApp.setActivationPolicy(.regular),并使用 NSApp.activate(ignoringOtherApps: true) 激活应用。如果应用有意仅限菜单栏运行,请说明 .accessory/不显示 Dock 的行为是经过考虑的产品选择。
  • 优先使用能适配系统的颜色、材质和语义前景样式。除非所需设计明确要求自定义的非自适应主题,否则脚手架和示例中应避免固定的白色/浅色背景。
  • 默认不要用不透明的自定义 Color(...) 或 Color(nsColor: .windowBackgroundColor) 填充 NavigationSplitView 侧边栏或根窗口窗格。除非用户明确要求自定义的不透明表面,否则优先使用原生 macOS 侧边栏/窗口材质和系统提供的背景。在侧边栏-详情-检查器布局中,应让侧边栏保持标准的源列表/材质外观,仅在需要时为详情或检查器内容卡片使用自定义背景。
  • 使用 @SceneStorage 存储每个窗口的临时状态,使用 @AppStorage 存储持久的用户偏好设置。
  • 明确并稳定地管理选择状态。macOS 布局通常以侧边栏选择为核心,而不是推入式导航。
  • 如果应用需要始终可见的结构,请优先使用 NavigationSplitView 或经过深思熟虑的手动分栏布局,而不是 iOS 风格的堆叠流程。
  • 对于 List(...).listStyle(.sidebar) 和 NavigationSplitView 侧边栏,优先采用扁平的原生行,并使用标准系统选择/高亮行为。行的视觉样式应轻盈、类似 Mail:最多包含一个前置图标、一行醒目的标题,以及一行可选的次要详情(使用 .secondary)。避免堆叠元数据行、重复的内联工具图标,或在侧边栏中显示密集的多列状态文本。除非用户明确要求高度自定义的侧边栏样式,否则应将卡片式和元数据密集型界面留给详情或检查器窗格。
  • 适当时,应让主要操作既能从界面控件中找到,也能通过键盘快捷键触发。
  • 优先使用 SwiftUI 原生场景和视图。如果需要底层窗口、响应者链、文本系统或面板控制,请切换到 appkit-interop。

有关侧边栏行和分栏视图背景的具体示例,请阅读 references/split-inspectors.md。

状态所有权概要

选择与所有权模型相符、作用范围最窄的状态工具:

场景首选模式
本地视图或控件状态@State
子视图修改由父视图拥有的值状态@Binding
macOS 14+ 上由根视图拥有的引用模型使用 @Observable 类型的 @State
子视图读取或修改注入的 @Observable 模型将其作为存储属性显式传入
窗口级临时选择或展开状态可行时使用 @SceneStorage,否则使用场景拥有的 @State
共享的用户偏好设置@AppStorage
共享的应用服务或配置@Environment(Type.self)
旧版目标平台上的旧式引用模型在所有者处使用 @StateObject,注入时使用 @ObservedObject

先选择所有权位置,再选择属性包装器。不要习惯性地把简单的桌面状态改造成视图模型。

横切参考

  • references/components-index.md:场景和组件指南的入口。
  • references/windowing.md:如何在 WindowGroup、Window、DocumentGroup 和窗口打开模式之间进行选择。
  • references/settings.md:专用设置场景、SettingsLink 和偏好设置布局。
  • references/commands-menus.md:命令菜单、键盘快捷键、焦点值和桌面操作路由。
  • references/split-inspectors.md:侧边栏、分栏视图、选择驱动的布局和检查器。
  • references/menu-bar-extra.md:菜单栏附加项的结构及适用场景。

反模式

  • 用一个巨大的 ContentView 假装整个应用只有一个屏幕。
  • 在单个 Swift 文件中包含 @main 应用、所有视图、模型、存储、网络/进程客户端、格式化器和扩展。只有在上文所述新应用规模阈值以下的微型临时代码片段中才可以这样做。
  • 直接将面向触控的交互模型从 iOS 移植过来,却不提供桌面端交互方式。
  • 将核心操作隐藏在手势后面,却不提供菜单、工具栏或键盘操作路径。
  • 仅围绕 Window(...) 场景构建菜单栏加窗口的应用,然后期待主窗口在启动时出现。主启动窗口应使用 WindowGroup(..., id:),并将 Window(...) 留给辅助或按需打开的窗口。
  • 在菜单栏附加项中直接呈现完整且不限长度的文档标题、提示词或消息文本。菜单项标签应不超过 30 个字符;较长内容应移至专用窗口或详情视图。
  • 将设置视为主内容窗口中的另一个导航目的地。
  • 在没有明确设计要求时,在全新脚手架中硬编码 .background(.white)、Color.white 或固定的浅色调色板。
  • 在 .sidebar 列表中将每个侧边栏项都包裹在大型圆角自定义卡片中,这会破坏原生源列表的密度、对齐和选择行为;除非用户明确要求定制视觉风格的侧边栏。
  • 构建包含多个重复图标、三行或更多文本,或密集排列的内联元数据计数器/时间戳/模型的侧边栏行。侧边栏行应只保留一个图标和一到两行文本,将更多元数据移至详情窗格。
  • 默认使用不透明的自定义颜色填充 NavigationSplitView 侧边栏或根窗口窗格,而不是让侧边栏采用原生源列表/材质外观,并将自定义背景留给实际的内容卡片。
  • 对于需要稳定侧边栏选择和详情窗格的布局,使用推入式导航。
  • 在正确使用 SwiftUI 场景和命令 API 之前就转而使用 AppKit。

新建 macOS 场景或视图的工作流

  1. 编写子视图之前,先定义场景类型和所有权模型。
  2. 决定哪些操作应放在内容区、工具栏、命令、检查器或设置中。
  3. 绘制选择模型和布局草图:侧边栏-详情、编辑器-检查器、文档窗口或实用工具窗口。
  4. 为应用入口、根布局、功能视图、模型、存储、服务和辅助工具创建文件/文件夹结构。
  5. 使用小型且职责明确的子视图和显式输入来构建,而不是使用巨大的计算片段。
  6. 为桌面端重要操作添加键盘快捷键,并通过菜单或工具栏提供入口。
  7. 通过构建和快速可用性检查来验证流程:多窗口假设、设置入口以及选择稳定性。

组件参考

使用 references/components-index.md 作为入口。每个组件参考都应包括:

  • 意图和最适合的场景
  • 遵循桌面端惯例的最简用法模式
  • 易错之处和可发现性说明
  • 何时退回使用 appkit-interop

评论

支持 Markdown