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.

ReservedRegionExample.swift
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 reservedRegion modifier when you only need insets for overlay chrome.
  • Query .division when columns or grids must split around the hinge.
  • Query .occlusion when drawing must miss camera coverage; pass .includeInactive only when a structural choice must stay stable across poses.
ReservedRegionsGeometry.swift
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.

IncludeInactiveRegions.swift
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:

  • NavigationStack and NavigationSplitView
  • TabView
  • List and ScrollView
  • 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.