Desarrolladores
Regiones reservadas de iPhone Duo: mantén tu interfaz fuera del pliegue
Usa las regiones reservadas de iPhone Duo en SwiftUI para localizar el pliegue y las cámaras: reservedRegions(kind:), .division vs .occlusion y .includeInactive.
Por la redacción de AppleDuoPublicado 9 min de lectura
En esta página
- ¿Qué son las regiones reservadas en iPhone Duo?
- ¿Cómo leo las regiones reservadas en SwiftUI?
- ¿Cuándo está activa la región de división del pliegue?
- ¿Qué contiene una ReservedRegion?
- ¿Cómo mantengo botones y texto fuera del pliegue?
- ¿Qué implican las regiones reservadas para el diseño de juegos?
- Conclusiones clave
Cuando iPhone Duo está parcialmente plegado, el centro de la pantalla interior se curva. El texto que cruza el pliegue cuesta leerlo, y un botón que cae en él cuesta pulsarlo. Las cámaras exterior e interior también ocupan espacio. Las regiones reservadas de iPhone Duo son la forma en que el sistema le dice a tu app dónde están esas zonas, para que mantengas tu propia interfaz fuera de ellas. Esta guía cubre la API de SwiftUI, cuándo cuenta el pliegue como activo, qué contiene una región y qué significa todo esto para los juegos que se juegan en modo mesa.
Las regiones reservadas son nuevas en iOS 27.1 y están disponibles en SwiftUI y UIKit. La charla de Apple Prepare your app for iPhone Duo dice que necesitas Xcode 27.1 para la experiencia de iPhone Duo a pantalla completa. Las API son nuevas, así que los detalles pueden cambiar entre versiones. Hemos escrito esto a partir de la documentación de Apple, del Tech Talk Strike a pose with adaptive layouts on iPhone Duo y de publicaciones del desarrollador de iOS Sarun Wongpatcharapakorn (@sarunw). No hemos medido estos valores en hardware.
¿Qué son las regiones reservadas en iPhone Duo?
Una región reservada es una zona de tu vista que reserva otra cosa, normalmente el hardware del dispositivo. Sarun lo explica de forma sencilla: las regiones reservadas te indican la zona donde no deberías poner tu interfaz.
En el Tech Talk, Apple enumera tres en iPhone Duo: la cámara exterior, la cámara interior mientras está activa y el pliegue. Las hay de dos tipos.
| Tipo | Qué significa | Ejemplo en iPhone Duo | Qué hacer |
|---|---|---|---|
.occlusion | Algo tapa parte de tu vista | Cámara exterior, cámara interior, Dynamic Island | Saca el contenido de esa zona |
.division | Algo parte tu vista en varias zonas | El pliegue | Pon contenido a ambos lados |
El pliegue es una división porque divide una zona grande en dos más pequeñas. Tu contenido no queda oculto ahí, pero todo lo que lo cruza es difícil de usar.
La mayoría de las apps no necesitan leer estas regiones. La documentación de Apple dice que las vistas del framework, como las split views, las barras de pestañas, las alertas, los menús contextuales y las hojas, ya se ajustan al pliegue y a las cámaras. Necesitas esta API para interfaces personalizadas: un control flotante, un overlay propio, el HUD de un juego o cualquier cosa que coloques con frames explícitos o un Layout personalizado. En los foros de desarrolladores, un ingeniero de Apple dio el mismo consejo: prioriza los contenedores integrados, usa ArrangementView para diseños personalizados de dos vistas y usa regiones reservadas para los controles colocados a mano.
¿Cómo leo las regiones reservadas en SwiftUI?
Envuelve tu contenido en un GeometryReader y llama a reservedRegions(kind:) en el proxy. Esta es la llamada que muestra Sarun:
GeometryReader { proxy in
let regions = proxy.reservedRegions(kind: .division)
}
La firma completa en la página de documentación de Apple es:
func reservedRegions(
kind: ReservedRegion.Kind,
options: ReservedRegion.QueryOptions = [],
layoutDirectionBehavior: LayoutDirectionBehavior = .mirrors
) -> [ReservedRegion]
Devuelve solo las regiones que se solapan con tu vista, con frames en el espacio de coordenadas de tu vista. Si una región solo se solapa en parte con tu vista, su frame puede empezar en coordenadas negativas o extenderse más allá del tamaño de tu vista.
El Tech Talk también menciona onGeometryChange como otra forma de obtener un geometry proxy. Como ReservedRegion es Equatable, puedes observar las regiones y guardarlas en el estado. Este es nuestro esbozo del patrón, no código de ejemplo de Apple:
struct GameBoard: View {
@State private var folds: [ReservedRegion] = []
var body: some View {
BoardView(folds: folds)
.onGeometryChange(for: [ReservedRegion].self) { proxy in
proxy.reservedRegions(kind: .division)
} action: { newValue in
folds = newValue
}
}
}
En UIKit, llama a reservedRegions(kind:) en una UIView y lee el frame de cada región:
let regions = view.reservedRegions(kind: .division)
let frames = regions.map(\.frame)
Si necesitas reaccionar al propio ángulo de la bisagra y no al espacio que ocupa, consulta estados de la bisagra de iPhone Duo y onHingeChange.
¿Cuándo está activa la región de división del pliegue?
El pliegue no siempre es un problema. Cuando iPhone Duo está abierto en plano, la pantalla es continua y el contenido puede cruzar el centro. Por eso la región de división se activa y desactiva según la postura.
| Postura | Región de división del pliegue | ¿Se devuelve por defecto? |
|---|---|---|
| Totalmente abierto, plano | Inactiva | No |
| Parcialmente abierto, como un libro | Activa, en vertical | Sí |
| Parcialmente abierto, como un portátil | Activa, en horizontal | Sí |
Sarun señala que, por defecto, reservedRegions devuelve solo las regiones activas, y la división del pliegue solo está activa cuando el dispositivo está plegado. La documentación de ReservedRegion de Apple dice lo mismo: cuando iPhone Duo está totalmente abierto, el método no devuelve regiones de división. La cámara interior funciona igual, como una región de oclusión que solo está activa mientras la cámara está en uso. La cámara exterior siempre está activa.
Para obtener también las regiones inactivas, pasa .includeInactive:
GeometryReader { proxy in
let regions = proxy.reservedRegions(
kind: .division,
options: .includeInactive)
let foldIsActive = regions.contains { $0.isActive }
Text(foldIsActive ? "Folded" : "Flat")
}
¿Para qué quieres una región inactiva? Apple da dos motivos. Una región inactiva sigue teniendo un frame, así que puedes dejarle espacio y evitar que tu diseño salte cuando alguien pliega el dispositivo. Y puedes tomar decisiones generales a partir de ella, como preferir un número par de columnas en una cuadrícula siempre que exista una división. El Tech Talk añade que la región del pliegue tiene ancho cero cuando el dispositivo está plano, así que usa las regiones inactivas para decisiones como estas, no para un espaciado exacto.
¿Qué contiene una ReservedRegion?
Cada región es un valor pequeño con cinco propiedades. Todas figuran en la documentación de Apple para iOS 27.1.
| Propiedad | Tipo | Qué te indica |
|---|---|---|
frame | CGRect | Dónde está la región, en las coordenadas de tu vista y en puntos, con los márgenes incluidos |
margins | EdgeInsets | Espacio extra alrededor de la zona reservada que mantiene alejado el contenido interactivo |
isActive | Bool | Si la región afecta a tu vista en este momento |
kind | ReservedRegion.Kind | .occlusion o .division |
id | ReservedRegion.ID | Un identificador estable entre consultas |
Hay tres detalles fáciles de pasar por alto. Primero, (0, 0) es la esquina superior inicial de la vista desde la que lees la región, no de la pantalla. Lee las regiones en la misma vista que coloca tu contenido, para que las coordenadas coincidan. En un Layout personalizado, haz los cálculos desde cero y suma bounds.origin solo al colocar cada subvista.
Segundo, el frame ya incluye los márgenes, así que no los sumes de nuevo. Tercero, los frames se reflejan por defecto en los idiomas de derecha a izquierda. Si tu contenido no se invierte con la dirección del diseño, pasa layoutDirectionBehavior: .fixed para obtener frames sin reflejar.
Para hacerte una idea de la escala, la demo de Sarun de la pantalla exterior muestra dos regiones de oclusión activas: una de 37 × 37 puntos en (399, 29) y otra de 84 × 170 puntos en (382, 0). Cubren la cámara y la zona de estado junto a ella, en la esquina superior final. Tómalas como un ejemplo de iOS 27.x, no como constantes. Lee los frames en tiempo de ejecución, porque son relativos a tu vista y pueden cambiar entre versiones. Para la parte del área segura del mismo problema, consulta áreas seguras y márgenes de contenido en iPhone Duo.
¿Cómo mantengo botones y texto fuera del pliegue?
Cuando hay una división activa, mantén cada vista entera a un lado. Compara el ancho y el alto del frame para saber en qué dirección va el pliegue y luego dimensiona tus paneles a su alrededor. Esta vista está adaptada de la documentación de Apple:
struct SplitContent: View {
var body: some View {
GeometryReader { proxy in
if let fold = proxy.reservedRegions(kind: .division).first,
fold.frame.width > fold.frame.height {
// Plegado como un portátil: apila los paneles.
VStack(spacing: 0) {
ScreenView()
.frame(height: fold.frame.minY)
Color.clear
.frame(height: fold.frame.height)
ControlsView()
.frame(height: proxy.size.height - fold.frame.maxY)
}
} else {
// Plano, o plegado como un libro: un solo diseño.
SingleLayout()
}
}
}
}
El espaciador transparente mide exactamente lo mismo que la división, así que nada cae en el pliegue. El ejemplo completo de Apple también gestiona el pliegue vertical, tipo libro, con un HStack. iPhone Duo tiene un solo pliegue, así que basta con leer .first.
Algunas reglas de las pautas de Apple ayudan aquí:
- Mueve solo lo necesario. Los controles que saltan lejos o desaparecen son difíciles de volver a encontrar. Prefiere ajustes pequeños y mueve juntos los controles relacionados.
- Deja que el contenido desplazable se desplace. Las listas y los scroll views no dividen sus filas alrededor del pliegue por defecto, y el Tech Talk dice que el contenido desplazable suele adaptarse por sí solo. Comprueba la división solo si una fila se vuelve difícil de leer o usar.
- Usa columnas pares. En una cuadrícula, un número par de columnas se divide limpiamente en el pliegue.
- Prioriza un contenedor. Si tu pantalla son dos vistas relacionadas, ArrangementView en SwiftUI las mantiene en lados opuestos del pliegue sin que tengas que leer las regiones tú.
¿Qué implican las regiones reservadas para el diseño de juegos?
Los juegos suelen dibujar su propia interfaz, así que el sistema no puede moverla por ti. Una barra de vida, un botón de disparo o una puntuación que cruza el pliegue es justo el contenido personalizado que Apple dice que revises.
La postura de mesa, plegado como un portátil y apoyado en una mesa, cambia la pregunta de diseño. Las pautas de diseño de Apple, según las resume el diseñador Blake Crosley, dicen que la zona superior funciona bien para contenido que se ve a distancia, y la inferior es adecuada para controles interactivos. Las pautas de Apple también piden que los juegos llenen la pantalla al cambiar de postura, que prefieran cambiar la proporción antes que añadir bandas negras y que mantengan coherentes los tamaños de texto y controles al redimensionar.
Varios juegos de AppleDuo están construidos en torno a esa división. En Battlefleet Duo, tu flota está en la pantalla inferior mientras las aguas enemigas se alzan, y dos jugadores pueden enfrentarse a ambos lados del pliegue. Greens: Mini-golf se pliega como un portátil: golpeas en la mitad inferior y la mitad erguida se convierte en una cámara de caddie. Describimos estos juegos a partir de sus fichas en la tienda; no sabemos qué API usan internamente.
Para tu propio juego, de la API se desprenden algunos patrones:
- Trata el pliegue como una costura en tu HUD. Ancla los controles táctiles a la mitad plana y el estado a la mitad erguida, usando el frame de la división como límite.
- Mantén despejadas las partes importantes del área de juego. Está bien que el arte de fondo cruce el pliegue, pero no un objetivo, una carta o una casilla que haya que pulsar.
- Planifica ambas orientaciones. Un pliegue tipo libro va en vertical, lo que encaja con una división como dos jugadores o dos tableros lado a lado. Un pliegue tipo portátil va en horizontal.
- Evita los saltos de diseño. Consulta con
.includeInactivey reserva el espacio con antelación si un cambio repentino estropearía la partida.
Hay más ejemplos en nuestra página Built for the Fold.
Conclusiones clave
- Las regiones reservadas, nuevas en iOS 27.1, marcan zonas que tu interfaz no debería usar. En iPhone Duo son la cámara exterior, la cámara interior mientras está activa y el pliegue.
- Llama a
proxy.reservedRegions(kind: .division)para el pliegue o a.occlusionpara las cámaras. UIKit tiene el mismo método enUIView. - La división del pliegue solo está activa cuando iPhone Duo está parcialmente plegado. Pasa
.includeInactivepara obtenerla en plano y compruebaisActive. - Cada
ReservedRegiontiene unframeen las coordenadas de tu vista, en puntos, con losmarginsya incluidos. Léelo en la vista que coloca tu contenido. - Los contenedores estándar ya gestionan el pliegue. Usa las regiones reservadas para controles personalizados, overlays y HUD de juegos, y mantén todo lo pulsable a un lado del pliegue.
A continuación, mira cómo ArrangementView gestiona el pliegue en diseños de dos vistas, o repasa la lista de comprobación para preparar tu app para iPhone Duo.
Preguntas frecuentes
¿Qué son las regiones reservadas en iPhone Duo?
Las regiones reservadas son zonas de la pantalla que reserva el hardware, así que tu contenido debe mantenerse alejado de ellas. En iPhone Duo hay tres: la cámara exterior, la cámara interior mientras está en uso y el pliegue.
¿Cómo obtengo el pliegue de iPhone Duo en SwiftUI?
Envuelve tu contenido en un GeometryReader y llama a proxy.reservedRegions(kind: .division). El pliegue se devuelve como una ReservedRegion cuyo frame está en el espacio de coordenadas de tu vista, en puntos, con sus márgenes ya incluidos.
¿Por qué reservedRegions devuelve un array vacío en un iPhone Duo plano?
Por defecto, el método devuelve solo las regiones activas, y la región de división del pliegue está inactiva cuando iPhone Duo está totalmente abierto. Pasa options: .includeInactive para obtenerla igualmente y luego comprueba isActive en cada región.
¿Qué diferencia hay entre las regiones de división y de oclusión?
Una región de oclusión tapa parte de tu vista, como una cámara o la Dynamic Island, así que sacas el contenido de ella. Una región de división parte tu vista en varias zonas, como el pliegue, así que distribuyes el contenido a ambos lados.
¿Necesito regiones reservadas si uso vistas estándar de SwiftUI?
Normalmente no. Apple dice que las split views, las barras de pestañas, las alertas, los menús contextuales y las hojas ya se ajustan al pliegue y a las cámaras. Revisa las regiones reservadas en overlays personalizados, controles flotantes y vistas que colocas con frames explícitos o un Layout personalizado.
Fuentes
- Strike a pose with adaptive layouts on iPhone Duo (Tech Talk) · Apple Developer
- ReservedRegion · Apple Developer Documentation
- reservedRegions(kind:options:layoutDirectionBehavior:) · Apple Developer Documentation
- Prepare your app for iPhone Duo (Tech Talk) · Apple Developer
- Designing for iPhone Duo · Apple Human Interface Guidelines
- How to know when active regions are changing? · Apple Developer Forums
- Designing for iPhone Duo · Blake Crosley
- Reserved regions tell you where you shouldn't put your UI · @sarunw on X
- reservedRegions returns only active regions by default; pass .includeInactive · @sarunw on X
- Position and size of ReservedRegion on iPhone Duo · @sarunw on X
Haz que el pliegue forme parte de tu app.
Mostramos apps y juegos que sacan partido de verdad al iPhone Duo. Envíanos la tuya con un enlace al App Store, o mira lo que han creado otros desarrolladores.