关于 swift-focusengine-pro
swift-focusengine-pro 是面向 Apple 平台焦点管理代码的审查技能,检查平台特定规则、无障碍、焦点恢复和布局,并给出具体问题及代码修正建议。
主要功能
- 01检查各平台的焦点规则
- 02识别焦点反模式
- 03审查焦点样式与恢复
- 04检查无障碍和异步处理模式
- 05按文件列出问题并提供代码修正
适用场景
- 01审查 SwiftUI 或 UIKit 焦点导航
- 02排查跨 Apple 平台应用的焦点问题
- 03检查键盘、遥控器、数码表冠或注视交互
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mhaviv/ swift-focusengine-agent-skill --skill swift-focusengine-pro安装后在 Claude Code 中输入/swift-focusengine-pro确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
CONTRIBUTING.mdLICENSECODE_OF_CONDUCT.md.gitignoreCHANGELOG.mdREADME.mdllms.txtpackage.json.claude-plugin/plugin.jsonmarketplace.json.github/pull_request_template.md.github/ISSUE_TEMPLATE/bug_report.mdfeature_request.mdagents/openai.yamlreferences/debugging.mdaccessibility-focus.mdasync-focus.mdanti-patterns.mdfocus-restoration.mdfocus-styling.mdios-focus.mdwatchos-focus.mduikit-focus.mdswiftui-focus.mdvisionos-focus.mdmacos-focus.mdlayout-patterns.mdrealitykit-focus.md详细介绍
审查焦点管理代码的正确性、现代 API 的使用情况,以及是否遵循 Apple 的焦点引擎规则。涵盖所有 Apple 平台。只报告确实存在的问题,不要吹毛求疵或臆造问题。
审查流程:
- 使用
references/anti-patterns.md检查关键反模式。 - 确定目标平台并加载相应参考资料:
- tvOS:
references/swiftui-focus.md和references/uikit-focus.md。 - iOS/iPadOS:
references/ios-focus.md(焦点组、光环、键盘导航)。 - watchOS:
references/watchos-focus.md(Digital Crown、顺序焦点)。 - visionOS:
references/visionos-focus.md(注视、悬停效果)和references/realitykit-focus.md(RealityKit 实体、手势、空间)。 - macOS:
references/macos-focus.md(键视图环、焦点环、NSView 焦点、菜单的 focusedValue、Mac Catalyst)。 - 跨平台:加载所有相关参考资料。
- tvOS:
- 使用
references/focus-styling.md检查焦点样式和视觉反馈。 - 使用
references/focus-restoration.md验证焦点恢复和数据重新加载处理。 - 使用
references/layout-patterns.md审查布局模式,确保焦点区段相互隔离。 - 使用
references/async-focus.md检查 async/await 和数据加载焦点模式。 - 使用
references/accessibility-focus.md验证无障碍集成。 - 使用
references/debugging.md检查调试和测试实践。
如果只做部分审查,仅加载相关参考文件。
核心说明
tvOS
- tvOS 使用基于焦点的导航模式——每个可交互元素都必须能通过 Siri Remote 的方向键访问。
- 焦点移动完全由几何位置决定——焦点引擎会从当前焦点视图沿滑动方向绘制一个矩形,并选择其中最近的可聚焦视图。
- 如果几何路径中没有视图,焦点就不会移动。就是这样。使用
.focusSection()(SwiftUI)或UIFocusGuide(UIKit)跨越间隔。 - 切勿在 tvOS 上使用
.disabled()切换交互状态——它会将视图从焦点链中完全移除。.allowsHitTesting(false)在 tvOS 上不可靠(可能会映射到isUserInteractionEnabled = false)。首选做法:在按钮闭包中控制操作,或对列表使用@FocusState+.disabled()双重门控模式(反模式 #25)。 prefersDefaultFocus(_:in:)在 tvOS 的ScrollView内不起作用——请改用defaultFocus(_:_:priority:)。注意:带有.userInitiated的defaultFocus只会在首次显示时触发,而不会在每次重新进入时触发。- 优先使用
ScrollPosition,而不是ScrollViewReader.scrollTo()——命令式的 scrollTo 会导致与焦点引擎之间出现反馈循环(反模式 #26)。 - 始终在 Apple TV 真机硬件上测试——模拟器中的焦点行为有所不同。
iOS/iPadOS
- 焦点是次要交互模式——仅在连接硬件键盘时启用。
- Tab 键在焦点组之间移动;方向键在组内移动。tvOS 不存在这种两级模型。
- 使用
focusGroupIdentifier(iOS 14+,UIKit)定义自定义焦点组——此 API 在 tvOS 上不可用。 - 使用
UIFocusHaloEffect自定义系统焦点环——tvOS 不提供此 API。 - 在集合视图/表格视图上设置
allowsFocus = true和selectionFollowsFocus = true,以支持键盘导航。 - 即使没有键盘焦点,应用也必须能正常使用——始终进行纯触控测试。
watchOS
- 焦点会将 Digital Crown 输入路由到正确的视图,并以绿色边框显示。
- 焦点按顺序移动(依据布局顺序),而非按空间位置/方向移动。
- watchOS 不提供
.focusSection()。 .focusable()必须放在.digitalCrownRotation()之前——反过来会导致表冠输入在没有提示的情况下失效。- 不要对系统控件(Picker、Stepper、Toggle)添加
.focusable()——它们已自行处理。
visionOS
- 眼动注视 = 悬停目标定位,而非焦点。
onHover(perform:)不会因注视而触发——只有指针设备才会触发。 - 使用
.hoverEffect()提供注视视觉反馈。系统控件会自动应用;自定义视图需要显式添加。 @FocusState只会在使用键盘(Magic Keyboard)、VoiceOver 或 Switch Control 时激活。- RealityKit 实体需要
InputTargetComponent+CollisionComponent+HoverEffectComponent才能支持注视交互。 .focusEffectDisabled()会隐藏键盘焦点环;.hoverEffectDisabled()会禁用注视悬停——两者并不相同。
macOS
- macOS 使用键视图循环——按 Tab/Shift-Tab 会按定义的顺序在视图之间移动。这不像 tvOS 那样基于空间。
- 自定义 NSView 子类必须重写
acceptsFirstResponder并返回true——其默认值为false,会导致视图无法通过 Tab 导航访问。 - 在 NSWindow 上设置
autorecalculatesKeyViewLoop = true会覆盖所有手动的nextKeyView连接。请选择一种方式。 - 自定义焦点环:在 NSView 上重写
focusRingType、focusRingMaskBounds和drawFocusRingMask()。 - 在 macOS 上,
focusedValue/focusedSceneValue对于让菜单栏命令响应当前选中项至关重要。 - Mac Catalyst:继承 iPad 的
UIFocusSystem。如果 iPad 应用不支持键盘焦点,Catalyst 应用也不会支持。 - Full Keyboard Access 默认关闭——大多数用户只能在文本字段和列表之间按 Tab,而不能在所有控件之间切换。
所有平台
- 切勿对 Buttons 或 NavigationLinks 添加
.focusable()——它们本身已可获得焦点。添加此修饰符会创建双重焦点包装器。 - 不要在同一视图层级分支中混用
@FocusState(SwiftUI)和 UIKit 焦点 API(setNeedsFocusUpdate)。 - VoiceOver 焦点(
@AccessibilityFocusState)与 UI 焦点(@FocusState)完全独立。
工具链状态(截至 Xcode 27 beta,2026 年 8 月)
- OS 26 恰好新增了一个焦点 API——
accessibilityDefaultFocus(_:_:)(SwiftUI,所有平台 26.0+;设置默认 VoiceOver 焦点;参见references/accessibility-focus.md)——且没有弃用任何焦点 API;OS 27 beta 也没有新增 API。此结论来自对已安装的五个平台 26.5 SDK 接口的扫描,而非仅依据发行说明。焦点相关的其他变化:Liquid Glass 改变了 tvOS 26 上已聚焦控件的外观(仅限 4K 第 2 代及更新设备——较旧设备保留玻璃效果之前的视觉样式);ControlSize在 tvOS 26+ 上可用;.sidebarAdaptableTabView(tvOS 18+)会将标签区域移至前导侧边栏;visionOS 26 新增可选的注视滚动(.scrollInputBehavior(.enabled, for: .look))。 - 27 SDK 要求在 iOS/iPadOS/tvOS/visionOS/Mac Catalyst 上使用基于场景的生命周期(不使用时应用无法启动;macOS 和 watchOS 不受影响);tvOS 27 还新增了 Dynamic Type——两者都会影响焦点示例的框架搭建和尺寸设置,但不会影响焦点 API。
- Swift 6.2:新建的 Xcode 26 项目默认采用模块范围的 MainActor 隔离;在需要同时兼容两种模式的示例中保留显式的
@MainActor(参见references/async-focus.md)。
输出格式
按文件整理发现的问题。对于每个问题:
- 指明文件和相关行号。
- 指出违反的规则(例如:“不要将普通控件从 tvOS 焦点链中移除——应限制操作,而不是使用
.disabled();反模式 #25 中有意采用的双@FocusState入口门控模式是唯一例外”)。 - 展示简短的修复前/修复后代码。
跳过没有问题的文件。最后按优先级总结影响最大的修改。
输出示例:
TopicsView.swift
第 49 行:.disabled() 会将视图从 tvOS 焦点链中移除(反模式 #1)。
// Before
TopicClipsGridView(...)
.disabled(!wrapper.isGridFocusable)
// After — gate the action, not the view
TopicClipsGridView(...)
.opacity(wrapper.isGridFocusable ? 1.0 : 0.5)
// Move the guard inside the button/action closures instead
第 72 行:垂直布局中的水平 ScrollView 缺少 .focusSection()。
// Before
ScrollView(.horizontal) {
HStack { /* row items */ }
}
// After
ScrollView(.horizontal) {
HStack { /* row items */ }
}
.focusSection()
总结
- 焦点中断(严重): 第 49 行的
.disabled()会将整个网格从焦点链中移除。 - 焦点跳转(较高): 缺少
.focusSection()会导致焦点在行之间跳转。
示例结束。
参考资料
references/anti-patterns.md— 会破坏焦点导航的关键错误:涵盖 tvOS/通用部分和 macOS 专属部分,共列出 30 条反模式。references/swiftui-focus.md— SwiftUI 焦点 API:@FocusState、focusSection、prefersDefaultFocus、focused、defaultFocus、onMoveCommand。references/uikit-focus.md— UIKit 焦点 API:UIFocusEnvironment、UIFocusGuide、shouldUpdateFocus、didUpdateFocus、preferredFocusEnvironments、UIFocusDebugger。references/focus-styling.md— 焦点视觉反馈:使用 isFocused 的 ButtonStyle、FocusBorder、悬停效果、缩放/阴影动画、macOS 焦点环样式。references/focus-restoration.md— 处理数据重新加载、导航和异步更新后的焦点。references/layout-patterns.md— 常见 tvOS 布局:集合表、侧边栏+内容、标签栏、水平内容架。references/ios-focus.md— iOS/iPadOS 专属:焦点组、focusGroupIdentifier、UIFocusHaloEffect、键盘导航、allowsFocus、selectionFollowsFocus。references/watchos-focus.md— watchOS 专属:Digital Crown 路由、顺序焦点、digitalCrownRotation、焦点顺序。references/visionos-focus.md— visionOS 专属:注视与焦点、悬停的区别、HoverEffect、HoverEffectGroup、RealityKit HoverEffectComponent、空间输入。references/macos-focus.md— macOS 专属:键视图循环、NSView 焦点(acceptsFirstResponder、canBecomeKeyView)、焦点环自定义、菜单的 focusedValue、Mac Catalyst、完全键盘访问。references/realitykit-focus.md— RealityKit 实体悬停:HoverEffectComponent、碰撞形状、手势、着色器效果、SwiftUI+RealityKit 混合层级结构。references/async-focus.md— 异步焦点模式:@MainActor 协调、数据加载后的焦点、NavigationStack 弹出、Task 取消、防抖。references/accessibility-focus.md— 辅助功能集成:@AccessibilityFocusState、VoiceOver 与焦点、完全键盘访问、切换控制、减少动态效果。references/debugging.md— UIFocusDebugger、_whyIsThisViewNotFocusable、启动参数、快速查看、macOS 第一响应者调试。
评论
支持 Markdown