iPhone Duo Adaptation Field Notes: 8 Layout Pitfalls from a Shipping Photo App
Any SwiftUI app being adapted for iPhone Duo will hit the same class of layout feedback loops, safe-area double subtraction, and toolbar identity regressions; the article shows how to diagnose and test each one.
Getting an existing iPhone app onto iPhone Duo means more than widening the canvas and moving panels. One photo editor author walked through every screen, from home to export, and found that each flow had its own spatial failure. Three-column catalogs overflowed the inspector, titles and sliders never quite aligned, and popovers squeezed the photo out of view. Some problems only showed up after a rotation: buttons retained correct enabled states but landed in wrong positions, and one portrait-to-landscape rotation triggered a persistent layout feedback loop.
The root cause of the hang was a circular dependency between navigation placement and inspector presence. With top navigation, the workspace solver had enough width for a tool rail, canvas, and 280pt inspector; switching to side navigation reduced available width so the inspector dropped out, which moved the navigation back to the top, reactivating the inspector. The fix made region selection re-use the same inspector feasibility check as structural selection, and added an eight-iteration regression test that cycles between the two navigation states.
Other fixes include reading actual slider track insets from UIKit, separating window size from content size so root resolution doesn't depend on navigation, treating safe areas in one layer only, and using system Sheets for detail popovers so they take the current external height. The author ends with a three-level verification strategy: pure value/strategy regressions, full integration build, and runtime checks of button positions, rotation continuity, and scrolling.
The layout feedback loop shows that navigation placement and feature density must be decided against the same constraint set; if the solver's choice changes navigation, and navigation changes the solver's input, you get oscillation.
Treating 'regular' width as iPad-only is a trap once a foldable expands a phone to regular dimensions; every branch that does this needs rechecking.
A one-layer safe-area contract works better than per-container inset subtraction on a device with dynamic division and occlusion regions.
Only testing a single width/height snapshot cannot catch layout instability; feeding consecutive states to the solver is the only way to verify convergence.
Catalog layout must be evaluated with the same content-width budget as the surrounding grid; swapping only the GridItem to flexible while previews stay fixed-width still overflows.