swiftui-iphone-duo

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

SwiftUI iPhone Duo

SwiftUI iPhone Duo

Do not design a separate “Duo version” of the app.
Start with an adaptive SwiftUI interface that works across continuously changing widths and heights. Add Duo-specific behavior only when the fold, hinge, second display, or vertical system bars materially improve the experience.
The target is not “Make this app support iPhone Duo.” The target is:
Make this app excellent at every size, then use Duo's unique hardware where it creates additional value.
Before reviewing or changing layout, read the full rulebook: reference.md.
不要为应用设计单独的“Duo版本”。
首先构建可适配宽高持续变化的自适应SwiftUI界面。仅当折叠、铰链、副显示屏或垂直系统栏能显著提升体验时,再添加Duo专属功能。
我们的目标不是“让这款应用支持iPhone Duo”,而是:
让这款应用在所有尺寸下都表现出色,再利用Duo的独特硬件创造额外价值。
在审查或修改布局前,请阅读完整规则手册:reference.md。

When to use

适用场景

  • User asks to support iPhone Duo, a foldable iPhone, hinge, fold, or two displays.
  • User asks for adaptive SwiftUI layout across compact → wide, including multitasking.
  • Code uses
    UIDevice
    ,
    UIScreen.main.bounds
    , idiom, orientation,
    isDuo
    , or
    isFolded
    for layout.
  • Work involves
    ArrangementView
    , reserved regions,
    onHingeChange
    , or scene accessories.
  • 用户要求支持iPhone Duo、可折叠iPhone、铰链、折叠或双显示屏。
  • 用户要求实现从紧凑到宽屏的自适应SwiftUI布局,包括多任务场景。
  • 代码中使用
    UIDevice
    、
    UIScreen.main.bounds
    、idiom、orientation、
    isDuo
    或
    isFolded
    来处理布局。
  • 工作涉及
    ArrangementView
    、Reserved Regions、
    onHingeChange
    或scene accessories。

Related skills

相关技能

SkillWhen to load
swiftui-whats-new-27Toolbar overflow,
visibilityPriority
,
ToolbarOverflowMenu
,
.topBarPinnedTrailing
swiftui-specialistBroader SwiftUI layout and navigation correctness
swiftui-liquid-glassSystem bars and glass chrome on iOS 26+

技能加载时机
swiftui-whats-new-27工具栏溢出、
visibilityPriority
、
ToolbarOverflowMenu
、
.topBarPinnedTrailing
swiftui-specialist更广泛的SwiftUI布局与导航正确性问题
swiftui-liquid-glassiOS 26及以上版本的系统栏与玻璃质感界面

Optimization order

优化顺序

  1. Adaptive layout
  2. Adaptive navigation
  3. Adaptive toolbars and tabs
  4. Fold-safe positioning
  5. Duo-specific arrangements
  6. Hinge-driven interactions
  7. Second-display experiences
  1. 自适应布局
  2. 自适应导航
  3. 自适应工具栏与标签页
  4. 折叠安全定位
  5. Duo专属排布
  6. 铰链驱动交互
  7. 副屏体验

Progressive API tiers

渐进式API层级

Classify every change before writing code. Always complete Tier 1 before proposing Tier 2 or Tier 3.
Tier 1 — Universal adaptive improvements (do these first):
text
NavigationSplitView
adaptive TabView
adaptive grids
ViewThatFits
AnyLayout
size classes
container-relative sizing
system toolbars
safe-area correctness
These benefit all Apple platforms and window sizes.
Tier 2 — Duo-aware layout (only when needed):
text
Reserved Regions
ArrangementView
vertical toolbar behavior
Duo-specific safe-area handling
Tier 3 — Duo-exclusive experiences (only when the product benefits):
text
onHingeChange
hinge angle
scene accessories
multi-display interactions
multi-scene Duo workflows

编写代码前先对所有修改进行分类。必须先完成第1层,再提出第2或第3层的修改。
第1层 — 通用自适应改进(优先执行):
text
NavigationSplitView
adaptive TabView
adaptive grids
ViewThatFits
AnyLayout
size classes
container-relative sizing
system toolbars
safe-area correctness
这些改进适用于所有Apple平台和窗口尺寸。
第2层 — Duo感知布局(仅在需要时使用):
text
Reserved Regions
ArrangementView
vertical toolbar behavior
Duo-specific safe-area handling
第3层 — Duo专属体验(仅当产品能从中受益时使用):
text
onHingeChange
hinge angle
scene accessories
multi-display interactions
multi-scene Duo workflows

Workflow

工作流程

Copy and track progress:
- [ ] 1. Read reference.md
- [ ] 2. Review screens with the decision tree
- [ ] 3. Flag red-flag patterns with file evidence
- [ ] 4. Classify each change as Tier 1 / 2 / 3
- [ ] 5. Implement Tier 1 first
- [ ] 6. Apply Tier 2/3 only when space-based layout is insufficient
- [ ] 7. Keep state above adaptive layout; verify continuity across widths
复制并跟踪进度:
- [ ] 1. Read reference.md
- [ ] 2. Review screens with the decision tree
- [ ] 3. Flag red-flag patterns with file evidence
- [ ] 4. Classify each change as Tier 1 / 2 / 3
- [ ] 5. Implement Tier 1 first
- [ ] 6. Apply Tier 2/3 only when space-based layout is insufficient
- [ ] 7. Keep state above adaptive layout; verify continuity across widths

1) Review existing UI

1) 审查现有UI

Walk every SwiftUI screen with the decision tree below. Flag:
  • Device identity used as a layout switch (
    UIDevice
    , idiom, model,
    isDuo
    ,
    isFolded
    )
  • UIScreen.main.bounds
    or orientation used for ordinary layout
  • Fixed column counts, hardcoded sidebar widths, arbitrary
    if width > N
  • Separate compact vs expanded view hierarchies with duplicated state
  • Custom toolbars / tab bars that cannot move to a vertical edge
  • Critical content that would sit on the fold
  • Wide layouts that only stretch instead of exposing hierarchy
  • Hinge angle used to decide sidebar, columns, or navigation
按照下方的决策树逐一检查每个SwiftUI界面。标记以下问题:
  • 将设备标识用作布局切换依据(
    UIDevice
    、idiom、机型、
    isDuo
    、
    isFolded
    )
  • 使用
    UIScreen.main.bounds
    或orientation处理常规布局
  • 固定列数、硬编码侧边栏宽度、随意的
    if width > N
    判断
  • 紧凑与展开视图层级分离,状态重复
  • 无法移动到垂直边缘的自定义工具栏/标签栏
  • 会落在折叠线上的关键内容
  • 宽屏布局仅拉伸内容,未展现层级结构
  • 使用铰链角度决定侧边栏、列数或导航

2) Implement or refactor

2) 实现或重构

  1. Replace device checks with container space: size classes,
    ViewThatFits
    ,
    AnyLayout
    , adaptive grids,
    containerRelativeFrame
    /
    onGeometryChange
    .
  2. Prefer
    NavigationSplitView
    for collection → selection → detail. Prefer adaptive
    TabView
    (
    .sidebarAdaptable
    ) over a hand-built sidebar.
  3. Prefer system
    .toolbar
    /
    ToolbarItem
    /
    ToolbarOverflowMenu
    so bars can become vertical.
  4. Keep one view hierarchy; hoist navigation, scroll, selection, editor, and playback state above layout.
  5. Use extra width for panes, inspectors, columns, and persistent navigation — not longer text lines. Cap readable content (e.g.
    .frame(maxWidth: 700)
    ).
  6. Move fold-sensitive controls locally. Do not rebuild the whole screen because a reserved region appeared.
  7. Use
    ArrangementView
    only for one two-part experience (player + playlist, editor + inspector). Do not use it as app navigation.
  8. Use
    onHingeChange
    / hinge angle only for physical interaction. Layout reacts to space. Interaction may react to hinge state.
  9. For the outer display, use scene accessories. Do not target
    innerDisplay
    /
    outerDisplay
    as independent canvases.
  1. 用容器空间替代设备检查:size classes、
    ViewThatFits
    、
    AnyLayout
    、自适应网格、
    containerRelativeFrame
    /
    onGeometryChange
    。
  2. 对于集合→选择→详情的结构,优先使用
    NavigationSplitView
    。优先使用自适应
    TabView
    (
    .sidebarAdaptable
    )而非手动构建的侧边栏。
  3. 优先使用系统
    .toolbar
    /
    ToolbarItem
    /
    ToolbarOverflowMenu
    ,以便工具栏可转为垂直布局。
  4. 保持单一视图层级;将导航、滚动、选择、编辑器和播放状态提升到布局之上。
  5. 将额外宽度用于窗格、检查器、列和持久导航——而非拉长文本行。为可读内容设置最大宽度(例如
    .frame(maxWidth: 700)
    )。
  6. 局部移动对折叠敏感的控件。不要因为出现Reserved Regions而重建整个界面。
  7. ArrangementView
    仅用于由两部分组成的体验(播放器+播放列表、编辑器+检查器)。不要将其用作应用导航。
  8. onHingeChange
    / 铰链角度仅用于物理交互。布局响应空间变化,交互可响应铰链状态。
  9. 对于外屏,使用scene accessories。不要将
    innerDisplay
    /
    outerDisplay
    作为独立画布来开发。

3) Untestable Duo behavior

3) 暂无法测试的Duo行为

Until the project can be tested with the iPhone Duo simulator in Xcode 27.1:
The agent may:
  • improve general adaptability
  • remove device assumptions
  • adopt standard adaptive containers
  • prepare code boundaries for Duo-specific APIs
  • identify likely fold-sensitive UI
The agent should avoid:
  • hardcoding predicted hinge coordinates
  • guessing exact Duo dimensions
  • adding untested Duo-only layout branches
  • restructuring working screens around assumptions
If Duo-specific behavior cannot yet be verified in the simulator, prefer preparation over speculative implementation.

在项目可通过Xcode 27.1中的iPhone Duo模拟器进行测试之前:
Agent 可以:
  • 提升通用适配性
  • 移除设备相关假设
  • 采用标准自适应容器
  • 为Duo专属API预留代码边界
  • 识别可能受折叠影响的UI
Agent 应当避免:
  • 硬编码预测的铰链坐标
  • 猜测Duo的精确尺寸
  • 添加未经测试的Duo专属布局分支
  • 基于假设重构正常运行的界面
如果Duo专属行为尚无法在模拟器中验证,优先做好准备,而非投机式实现。

Agent decision tree

Agent决策树

When reviewing a SwiftUI screen, evaluate it in this order.
  1. Does the layout work across continuously changing widths?
    If no: fix the general adaptive layout first.
  2. Is navigation manually switching between phone and tablet implementations?
    If yes: investigate
    NavigationSplitView
    , adaptive
    TabView
    , or another system navigation container.
  3. Are there fixed widths or screen-size assumptions?
    If yes: replace them with container-relative layout where possible.
  4. Does the wide layout simply stretch?
    If yes: look for a sidebar, detail pane, inspector, additional columns, or supplementary content.
  5. Could important content intersect the fold?
    If yes: use reserved-region-aware positioning.
  6. Are two related views being manually rearranged across layouts?
    If yes: evaluate
    ArrangementView
    ,
    ViewThatFits
    , or
    AnyLayout
    .
  7. Is there a custom toolbar or tab bar?
    If yes: determine whether SwiftUI system bars can replace it and adapt vertically.
  8. Does the requested behavior genuinely depend on physical hinge position?
    If no: do not use the hinge API.
    If yes: use
    onHingeChange
    and hinge state/angle.
  9. Would the outer display provide useful supplementary information?
    If yes: evaluate a scene accessory. Do not manually target a second screen.

审查SwiftUI界面时,按以下顺序评估:
  1. 布局是否能适配持续变化的宽度?
    若不能:先修复通用自适应布局。
  2. 导航是否在手机和平板实现之间手动切换?
    若是:调研
    NavigationSplitView
    、自适应
    TabView
    或其他系统导航容器。
  3. 是否存在固定宽度或屏幕尺寸假设?
    若是:尽可能用容器相对布局替换它们。
  4. 宽屏布局是否只是单纯拉伸?
    若是:考虑添加侧边栏、详情窗格、检查器、额外列或补充内容。
  5. 重要内容是否会与折叠线相交?
    若是:使用支持Reserved Regions的定位方式。
  6. 两个相关视图是否在不同布局间手动重排?
    若是:评估是否可使用
    ArrangementView
    、
    ViewThatFits
    或
    AnyLayout
    。
  7. 是否存在自定义工具栏或标签栏?
    若是:判断是否可用SwiftUI系统栏替代并支持垂直适配。
  8. 需求的行为是否确实依赖物理铰链位置?
    若否:不要使用铰链API。
    若是:使用
    onHingeChange
    及铰链状态/角度。
  9. 外屏是否能提供有用的补充信息?
    若是:评估使用scene accessory。不要手动针对副屏开发。

Agent rules

Agent规则

These are strict. Full explanations and code are in reference.md.
  1. When encountering device-specific layout logic, first attempt to replace it with layout behavior based on available container space.
  2. Prefer semantic adaptive containers over manual breakpoints. Order: system navigation/container → adaptive grid →
    ViewThatFits
    → size classes → exact geometry last.
  3. If a screen contains master/detail navigation, strongly prefer
    NavigationSplitView
    over a manually constructed
    HStack
    sidebar.
  4. Do not stretch narrow interfaces indefinitely. Use extra space to increase information density or introduce complementary panes.
  5. If repeated content appears in a grid, prefer minimum-item-width-driven adaptive columns (
    GridItem(.adaptive(minimum:))
    ).
  6. Use
    ViewThatFits
    when the question is “which arrangement fits?” rather than “which device am I on?”
  7. Prefer changing layout containers (
    AnyLayout
    ) over conditionally rebuilding separate view hierarchies.
  8. Never use
    UIScreen.main.bounds
    for SwiftUI layout unless there is an exceptional non-layout requirement.
  9. Avoid placing important interactive or semantic content across an active division region. Decorative backgrounds and scrolling content may usually cross the fold.
  10. Respond to fold interference locally before making a global structural change.
  11. Use
    ArrangementView
    only when the two views form one adaptive experience; do not substitute it for app navigation.
  12. Before creating a custom toolbar, verify that the design cannot be expressed with SwiftUI's toolbar APIs.
  13. Primary toolbar actions must remain visible; secondary actions may move into overflow as available bar space decreases.
  14. If tabs represent primary app sections and the wide layout benefits from persistent navigation, prefer SwiftUI's adaptive sidebar system.
  15. Never manually mirror one safe-area inset onto another edge. Duo safe areas can be asymmetric.
  16. Treat the fold like the spine of a book: backgrounds may span it; precise content should not.
  17. Layout reacts to space. Interaction may react to hinge state. Do not use
    hinge.angle
    for sidebar, columns, grid count, or navigation collapse.
  18. Use scene accessories for intentionally secondary display content; keep the main experience attached to the primary scene.
  19. A layout transition must not become an application-state transition.
  20. Every expansive layout must have a graceful path back through intermediate widths to compact presentation. Unfolded does not mean wide app.
  21. More available width does not imply wider text lines.
  22. Wide layouts should reveal more useful structure, not just more whitespace.
  23. Optimize for reach and grouping, not maximum geometric distribution.
  24. Always complete Tier 1 before proposing Tier 2 or Tier 3 changes.
  25. If Duo-specific behavior cannot yet be verified in the simulator, prefer preparation over speculative implementation.

这些是严格规则。完整说明和代码示例见reference.md。
  1. 遇到设备专属布局逻辑时,首先尝试用基于可用容器空间的布局行为替换。
  2. 优先使用语义化自适应容器,而非手动断点。优先级顺序:系统导航/容器 → 自适应网格 →
    ViewThatFits
    → size classes → 最后才是精确几何计算。
  3. 如果界面包含主从导航,强烈优先使用
    NavigationSplitView
    而非手动构建的
    HStack
    侧边栏。
  4. 不要无限拉伸窄界面。利用额外空间提升信息密度或引入补充窗格。
  5. 如果网格中存在重复内容,优先使用基于最小项宽度的自适应列(
    GridItem(.adaptive(minimum:))
    )。
  6. 当问题是“哪种排布适合?”而非“我在哪种设备上?”时,使用
    ViewThatFits
    。
  7. 优先更换布局容器(
    AnyLayout
    ),而非条件性重建独立的视图层级。
  8. 绝不要在SwiftUI布局中使用
    UIScreen.main.bounds
    ,除非有特殊的非布局需求。
  9. 避免将重要的交互或语义内容放置在活动分割区域上。装饰性背景和滚动内容通常可以跨越折叠线。
  10. 先局部响应折叠干扰,再进行全局结构修改。
  11. ArrangementView
    仅用于两个视图构成一个自适应体验的场景;不要用它替代应用导航。
  12. 创建自定义工具栏前,先确认该设计无法用SwiftUI的工具栏API实现。
  13. 主要工具栏操作必须保持可见;当工具栏可用空间减少时,次要操作可移入溢出菜单。
  14. 如果标签页代表应用主要板块,且宽屏布局能从持久导航中受益,优先使用SwiftUI的自适应侧边栏系统。
  15. 绝不要将一个安全区内边距手动镜像到另一边缘。Duo的安全区可能是不对称的。
  16. 将折叠线视为书脊:背景可以跨越它;精确内容不应跨越。
  17. 布局响应空间变化,交互可响应铰链状态。不得使用
    hinge.angle
    控制侧边栏、列数、网格数量或导航折叠。
  18. 专为副屏设计的内容使用scene accessories;主体验始终依附于主场景。
  19. 布局过渡绝不能变成应用状态过渡。
  20. 所有展开布局都必须能通过中间宽度顺畅回退到紧凑展示形态。展开状态不等于应用就是宽屏的。
  21. 可用宽度增加不代表文本行就要更宽。
  22. 宽屏布局应当展现更多有用的结构,而非仅仅增加空白。
  23. 针对可触达性和分组进行优化,而非最大化几何分布。
  24. 提出第2或第3层修改前,必须先完成第1层。
  25. 如果Duo专属行为尚无法在模拟器中验证,优先做好准备,而非投机式实现。

Code-review red flags

代码审查红旗项

Flag these when used for ordinary layout decisions:
swift
UIScreen.main.bounds
UIDevice.current.userInterfaceIdiom == .pad
if orientation == .landscape
if isIPhoneDuo
if isFolded { ... }
Also flag:
  • fixed large frames
  • hardcoded sidebar widths
  • fixed grid column counts
  • custom fake toolbars
  • content centered directly across the fold
  • duplicated compact and expanded state
  • layouts tested only at two widths
  • excessive full-width text
  • controls placed outside safe areas
Preferred replacements are in reference.md.

当以下内容用于常规布局决策时,标记为红旗项:
swift
UIScreen.main.bounds
UIDevice.current.userInterfaceIdiom == .pad
if orientation == .landscape
if isIPhoneDuo
if isFolded { ... }
同时标记以下问题:
  • 固定大尺寸frame
  • 硬编码侧边栏宽度
  • 固定网格列数
  • 自定义非系统工具栏
  • 内容直接居中跨越折叠线
  • 紧凑与展开状态重复
  • 仅在两种宽度下测试的布局
  • 过多的全宽文本
  • 控件放置在安全区外
推荐的替代方案见reference.md。

Review checklist

审查清单

  • No
    if isDuo
    / idiom / orientation /
    UIScreen
    layout branches
  • Layout follows container space across narrow → intermediate → wide
  • List/detail uses
    NavigationSplitView
    with preserved selection
  • Grids use
    GridItem(.adaptive(minimum:))
    rather than fixed column counts
  • Local rearrangements use
    ViewThatFits
    or
    AnyLayout
    , not duplicate hierarchies
  • Wide layout exposes hierarchy (sidebar, detail, inspector, columns) instead of stretching
  • Readable content has a maximum width
  • System toolbars/tabs used; items work horizontally and vertically
  • Important controls stay in (possibly asymmetric) safe areas
  • Critical content is not centered on the fold
  • State (nav, scroll, selection, editors, playback) survives fold/display changes
  • Hinge APIs used only for physical interaction
  • Second display uses scene accessories, not manual display targeting
  • Tier 2/3 APIs added only after Tier 1, and only when testable

  • 没有基于
    if isDuo
    / idiom / orientation /
    UIScreen
    的布局分支
  • 布局在窄→中→宽范围内均遵循容器空间变化
  • 列表/详情使用
    NavigationSplitView
    且保留选择状态
  • 网格使用
    GridItem(.adaptive(minimum:))
    而非固定列数
  • 局部重排使用
    ViewThatFits
    或
    AnyLayout
    ,而非重复层级
  • 宽屏布局展现层级结构(侧边栏、详情、检查器、列)而非拉伸内容
  • 可读内容设置了最大宽度
  • 使用系统工具栏/标签页;项目支持水平和垂直布局
  • 重要控件位于(可能不对称的)安全区内
  • 关键内容未居中在折叠线上
  • 状态(导航、滚动、选择、编辑器、播放)在折叠/显示屏切换时保持不变
  • 铰链API仅用于物理交互
  • 副屏使用scene accessories,而非手动针对显示屏开发
  • 第2/3层API仅在第1层完成后添加,且仅在可测试时添加

Additional resources

更多资源

  • Full 25 rules, API sketches, and before/after transformations: reference.md
  • 完整的25条规则、API示意图及改造前后对比:reference.md