見出し、例、コード、表、リンク、参照画像を含む原文を表示しています。
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.
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, orisFoldedfor layout. - Work involves
ArrangementView, reserved regions,onHingeChange, or scene accessories.
Related skills
| Skill | When to load |
|---|---|
| swiftui-whats-new-27 | Toolbar overflow, visibilityPriority, ToolbarOverflowMenu, .topBarPinnedTrailing |
| swiftui-specialist | Broader SwiftUI layout and navigation correctness |
| swiftui-liquid-glass | System bars and glass chrome on iOS 26+ |
Optimization order
- Adaptive layout
- Adaptive navigation
- Adaptive toolbars and tabs
- Fold-safe positioning
- Duo-specific arrangements
- Hinge-driven interactions
- Second-display experiences
Progressive API tiers
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):
NavigationSplitView
adaptive TabView
adaptive grids
ViewThatFits
AnyLayout
size classes
container-relative sizing
system toolbars
safe-area correctnessThese benefit all Apple platforms and window sizes.
Tier 2 — Duo-aware layout (only when needed):
Reserved Regions
ArrangementView
vertical toolbar behavior
Duo-specific safe-area handlingTier 3 — Duo-exclusive experiences (only when the product benefits):
onHingeChange
hinge angle
scene accessories
multi-display interactions
multi-scene Duo workflowsWorkflow
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 widths1) Review existing 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.boundsor 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
2) Implement or refactor
- Replace device checks with container space: size classes,
ViewThatFits,AnyLayout, adaptive grids,containerRelativeFrame/onGeometryChange. - Prefer
NavigationSplitViewfor collection → selection → detail. Prefer adaptiveTabView(.sidebarAdaptable) over a hand-built sidebar. - Prefer system
.toolbar/ToolbarItem/ToolbarOverflowMenuso bars can become vertical. - Keep one view hierarchy; hoist navigation, scroll, selection, editor, and playback state above layout.
- Use extra width for panes, inspectors, columns, and persistent navigation — not longer text lines. Cap readable content (e.g.
.frame(maxWidth: 700)). - Move fold-sensitive controls locally. Do not rebuild the whole screen because a reserved region appeared.
- Use
ArrangementViewonly for one two-part experience (player + playlist, editor + inspector). Do not use it as app navigation. - Use
onHingeChange/ hinge angle only for physical interaction. Layout reacts to space. Interaction may react to hinge state. - For the outer display, use scene accessories. Do not target
innerDisplay/outerDisplayas independent canvases.
3) Untestable Duo behavior
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.
Agent decision tree
When reviewing a SwiftUI screen, evaluate it in this order.
- Does the layout work across continuously changing widths?
If no: fix the general adaptive layout first.
- Is navigation manually switching between phone and tablet implementations?
If yes: investigate NavigationSplitView, adaptive TabView, or another system navigation container.
- Are there fixed widths or screen-size assumptions?
If yes: replace them with container-relative layout where possible.
- Does the wide layout simply stretch?
If yes: look for a sidebar, detail pane, inspector, additional columns, or supplementary content.
- Could important content intersect the fold?
If yes: use reserved-region-aware positioning.
- Are two related views being manually rearranged across layouts?
If yes: evaluate ArrangementView, ViewThatFits, or AnyLayout.
- Is there a custom toolbar or tab bar?
If yes: determine whether SwiftUI system bars can replace it and adapt vertically.
- 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.
- Would the outer display provide useful supplementary information?
If yes: evaluate a scene accessory. Do not manually target a second screen.
Agent rules
These are strict. Full explanations and code are in reference.md.
- When encountering device-specific layout logic, first attempt to replace it with layout behavior based on available container space.
- Prefer semantic adaptive containers over manual breakpoints. Order: system navigation/container → adaptive grid →
ViewThatFits→ size classes → exact geometry last. - If a screen contains master/detail navigation, strongly prefer
NavigationSplitViewover a manually constructedHStacksidebar. - Do not stretch narrow interfaces indefinitely. Use extra space to increase information density or introduce complementary panes.
- If repeated content appears in a grid, prefer minimum-item-width-driven adaptive columns (
GridItem(.adaptive(minimum:))). - Use
ViewThatFitswhen the question is “which arrangement fits?” rather than “which device am I on?” - Prefer changing layout containers (
AnyLayout) over conditionally rebuilding separate view hierarchies. - Never use
UIScreen.main.boundsfor SwiftUI layout unless there is an exceptional non-layout requirement. - Avoid placing important interactive or semantic content across an active division region. Decorative backgrounds and scrolling content may usually cross the fold.
- Respond to fold interference locally before making a global structural change.
- Use
ArrangementViewonly when the two views form one adaptive experience; do not substitute it for app navigation. - Before creating a custom toolbar, verify that the design cannot be expressed with SwiftUI's toolbar APIs.
- Primary toolbar actions must remain visible; secondary actions may move into overflow as available bar space decreases.
- If tabs represent primary app sections and the wide layout benefits from persistent navigation, prefer SwiftUI's adaptive sidebar system.
- Never manually mirror one safe-area inset onto another edge. Duo safe areas can be asymmetric.
- Treat the fold like the spine of a book: backgrounds may span it; precise content should not.
- Layout reacts to space. Interaction may react to hinge state. Do not use
hinge.anglefor sidebar, columns, grid count, or navigation collapse. - Use scene accessories for intentionally secondary display content; keep the main experience attached to the primary scene.
- A layout transition must not become an application-state transition.
- Every expansive layout must have a graceful path back through intermediate widths to compact presentation. Unfolded does not mean wide app.
- More available width does not imply wider text lines.
- Wide layouts should reveal more useful structure, not just more whitespace.
- Optimize for reach and grouping, not maximum geometric distribution.
- Always complete Tier 1 before proposing Tier 2 or Tier 3 changes.
- If Duo-specific behavior cannot yet be verified in the simulator, prefer preparation over speculative implementation.
Code-review red flags
Flag these when used for ordinary layout decisions:
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.
Review checklist
- [ ] No
if isDuo/ idiom / orientation /UIScreenlayout branches - [ ] Layout follows container space across narrow → intermediate → wide
- [ ] List/detail uses
NavigationSplitViewwith preserved selection - [ ] Grids use
GridItem(.adaptive(minimum:))rather than fixed column counts - [ ] Local rearrangements use
ViewThatFitsorAnyLayout, 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
Additional resources
- Full 25 rules, API sketches, and before/after transformations: reference.md

