ArrangementView is the highest-leverage new API for iPhone Duo. If your screen has a primary view and a related secondary one, this replaces a large amount of manual pose handling.
Setting it up
var body: some View {
NavigationStack {
ArrangementView {
PlayerView()
} secondary: {
UpNextView()
}
}
}
// UIKit
let arrangementVC = UIArrangementViewController()
let navController = UINavigationController(rootViewController: arrangementVC)
arrangementVC.setViewController(PlayerViewController(), for: .primary)
arrangementVC.setViewController(UpNextViewController(), for: .secondary)
The arrangement takes size classes, the view’s aspect ratio, and the active division regions as inputs, and decides whether to show the secondary view and what frame each view receives.
Choosing a style
Split — for a genuine main/detail relationship, such as a player with a transcript beneath it. It splits horizontally when the view is wider than tall and vertically when taller:
.arrangementViewStyle(.split)
Pin it to one axis when only one arrangement makes sense for your content:
.arrangementViewStyle(.split.axes(.horizontal))
Overlay — for a clear foreground/background relationship, where the secondary view floats over the primary:
.arrangementViewStyle(.overlay)
With an overlay, the secondary view should react to its own depth. Read the z-index and collapse when you are stacked over other content:
struct UpNextView: View {
@Environment(\.overlayArrangementZIndex) private var zIndex: Int
var minimization: UpNextMinimization {
zIndex > 0 ? .collapsed : .expanded
}
}
When not to use it
Apple describes a third pattern, displacement — moving elements based on available space — and warns against it for continuously scrolling content, where shifting the scroll position under the user is disorienting. A feed is usually better served by one column that changes width than by an arrangement.
How to verify
Cycle every pose in Device Hub and confirm the secondary view appears, moves, and disappears sensibly at each one, with no manual pose checks left in your own code.