ReservedRegion on iPhone Duo
Keep custom controls clear of the iPhone Duo fold and cameras with SwiftUI ReservedRegion, GeometryProxy reservedRegions, and UIKit UIViewReservedRegion.
Last updated
Quick answer
Use SwiftUI ReservedRegion (iOS 27.1) so custom controls stay clear of the fold and cameras. System containers already do this; you adopt the API for floating buttons, overlays, and hand-laid-out bars. Query GeometryProxy.reservedRegions as .division or .occlusion, and use UIViewReservedRegion in UIKit. Do not hardcode a hinge inset.
What it is
ReservedRegion is the SwiftUI API Apple shipped in iOS 27.1 so custom UI can claim the largest usable area while staying off hardware the system keeps for itself. The UIKit type is UIViewReservedRegion.
Three hardware ideas sit behind the API:
- Outer camera — always present. It can expand into the Dynamic Island when a Live Activity is running.
- Inner camera — reserved while the camera is active.
- Folding region — the hinge. Active while the device is folded; zero width when the device is flat.
Query those as .division when the fold splits usable areas, or as .occlusion when cameras cover pixels.
Apple recommendation
Apple recommends ReservedRegion instead of a hardcoded inset that matches only today's hinge. The fold geometry can change with pose, Live Activities, and future hardware; the API tracks that so your overlay does not.
SwiftUI modifier
Attach .reservedRegion(.systemControls) around custom chrome and pad with the region the system reports — use this when you own the overlay, not to wrap a NavigationStack that already avoids the fold.
ContentView()
.reservedRegion(.systemControls) { region in
CustomOverlay()
.padding(region.insets)
}Use this for a floating action button, a custom control strip, or a view drawn on top of content. Do not wrap an entire NavigationStack just to “avoid the fold” — that stack already does.
Common mistake
Don't hardcode a fold inset. A constant that looks right on today's hinge is wrong when the device flattens (the folding region goes to zero width), when the outer camera expands into the Dynamic Island, or when Apple ships a different hinge. Read region.insets instead.
GeometryProxy
Query GeometryProxy.reservedRegions when you are laying out by hand: .division is how the fold splits usable areas; .occlusion is pixels cameras cover.
- Prefer the
reservedRegionmodifier when you only need insets for overlay chrome. - Query
.divisionwhen columns or grids must split around the hinge. - Query
.occlusionwhen drawing must miss camera coverage; pass.includeInactiveonly when a structural choice must stay stable across poses.
GeometryReader { proxy in
let divisions = proxy.reservedRegions(kind: .division)
let occlusions = proxy.reservedRegions(kind: .occlusion)
// ...
}Use the returned frames to keep columns, grids, or drawing from sitting on the hinge or under a camera.
Inactive regions
Inactive reserved regions are excluded by default — pass .includeInactive only when a structural choice must stay stable across poses, such as an even column count so a grid does not reshuffle when the hinge goes to zero width.
GeometryReader { proxy in
let divisions = proxy.reservedRegions(
kind: .division,
options: .includeInactive
)
// Keep a split layout even when the hinge is inactive / zero-width.
}UIKit
The UIKit counterpart is UIViewReservedRegion, also introduced in iOS 27.1. Apply it to custom UIView chrome — floating buttons, overlay bars, hand-positioned controls — the same way SwiftUI apps use ReservedRegion. Standard UIKit containers already avoid reserved regions; do not rebuild that avoidance on top of UINavigationController or UITabBarController.
What you can skip
You do not need ReservedRegion if you already use NavigationStack, NavigationSplitView, TabView, List, ScrollView, alerts, sheets, or menus — those system containers already avoid reserved regions.
Skip this API for:
NavigationStackandNavigationSplitViewTabViewListandScrollView- Alerts, sheets, and menus
Adopt ReservedRegion only where you drew the chrome yourself. Reimplementing fold avoidance on top of system containers fights the layout the system already computed.
Frequently asked questions
What is ReservedRegion on iPhone Duo?
ReservedRegion is a SwiftUI API introduced in iOS 27.1 that keeps custom chrome clear of hardware the system reserves: the outer camera (always present, and able to expand into the Dynamic Island for Live Activities), the inner camera while it is active, and the folding region while the device is folded. The UIKit equivalent is UIViewReservedRegion.
Do I need ReservedRegion if I already use NavigationStack or TabView?
No. NavigationStack, NavigationSplitView, TabView, List, ScrollView, alerts, sheets, and menus already avoid reserved regions. Adopt ReservedRegion for custom chrome — floating buttons, overlays, and hand-laid-out bars — not to reimplement system layout.
What is the difference between .division and .occlusion?
.division describes how the fold splits usable areas. .occlusion describes pixels cameras cover. Query both from GeometryProxy when you are laying out by hand; the reservedRegion modifier is enough when you only need insets for overlay chrome.
When should I include inactive reserved regions?
Inactive regions are excluded by default. Pass options like .includeInactive when a structural choice must stay stable across poses — for example an even column count so a grid does not reshuffle when the hinge goes to zero width as the device flattens.
What is the UIKit equivalent of ReservedRegion?
UIViewReservedRegion, also introduced in iOS 27.1. Use it for custom UIView chrome the same way SwiftUI apps use ReservedRegion; do not hardcode a fold inset that matches only today’s hinge.