Développeurs
Régions réservées de l'iPhone Duo : éloignez votre interface du pli
Utilisez les régions réservées de l'iPhone Duo en SwiftUI pour repérer le pli et les caméras : reservedRegions(kind:), .division et .occlusion, .includeInactive.
Par la rédaction AppleDuoPublié le 9 min de lecture
Sur cette page
- Que sont les régions réservées sur l'iPhone Duo ?
- Comment lire les régions réservées en SwiftUI ?
- Quand la région de division du pli est-elle active ?
- Que contient une ReservedRegion ?
- Comment éloigner les boutons et le texte du pli ?
- Qu'impliquent les régions réservées pour la conception de jeux ?
- À retenir
Lorsque l'iPhone Duo est partiellement plié, le milieu de l'écran interne se courbe. Un texte qui traverse le pli est difficile à lire, et un bouton qui s'y trouve est difficile à toucher. Les caméras externe et interne occupent aussi de la place. Les régions réservées de l'iPhone Duo permettent au système d'indiquer à votre app où se trouvent ces zones, afin que vous puissiez en tenir votre propre interface à l'écart. Ce guide présente l'API SwiftUI, les moments où le pli est considéré comme actif, le contenu d'une région et ce que tout cela implique pour les jeux qui se jouent en mode sur table.
Les régions réservées sont nouvelles dans iOS 27.1 et disponibles en SwiftUI et en UIKit. Le Tech Talk d'Apple Prepare your app for iPhone Duo indique qu'il faut Xcode 27.1 pour l'expérience iPhone Duo en plein écran. Ces API sont nouvelles : certains détails peuvent changer d'une version à l'autre. Nous avons rédigé ce guide à partir de la documentation d'Apple, du Tech Talk Strike a pose with adaptive layouts on iPhone Duo et des publications du développeur iOS Sarun Wongpatcharapakorn (@sarunw). Nous n'avons pas mesuré ces valeurs nous-mêmes sur un appareil réel.
Que sont les régions réservées sur l'iPhone Duo ?
Une région réservée est une zone de votre vue réservée par autre chose, généralement le matériel de l'appareil. Sarun le résume simplement : les régions réservées vous indiquent la zone où vous ne devez pas placer votre interface.
Dans le Tech Talk, Apple en liste trois sur l'iPhone Duo : la caméra externe, la caméra interne lorsqu'elle est active, et le pli. Elles sont de deux types.
| Type | Signification | Exemple sur iPhone Duo | Que faire |
|---|---|---|---|
.occlusion | Quelque chose recouvre une partie de votre vue | Caméra externe, caméra interne, Dynamic Island | Déplacer le contenu hors de la zone |
.division | Quelque chose sépare votre vue en plusieurs parties | Le pli | Placer le contenu de part et d'autre |
Le pli est une division, car il sépare une grande zone en deux plus petites. Votre contenu n'y est pas masqué, mais tout ce qui le traverse est difficile à utiliser.
La plupart des apps n'ont pas besoin de lire ces régions. La documentation d'Apple indique que les vues du framework, comme les split views, barres d'onglets, alertes, menus contextuels et feuilles, s'adaptent déjà au pli et aux caméras. Vous avez besoin de cette API pour une interface personnalisée : une commande flottante, un overlay personnalisé, le HUD d'un jeu, ou tout ce que vous placez avec des frames explicites ou un Layout personnalisé. Sur les forums développeurs, un ingénieur d'Apple a donné le même conseil : privilégiez les conteneurs intégrés, utilisez ArrangementView pour les mises en page personnalisées à deux vues, et les régions réservées pour les commandes disposées manuellement.
Comment lire les régions réservées en SwiftUI ?
Enveloppez votre contenu dans un GeometryReader et appelez reservedRegions(kind:) sur le proxy. Voici l'appel que montre Sarun :
GeometryReader { proxy in
let regions = proxy.reservedRegions(kind: .division)
}
La signature complète sur la page de documentation d'Apple est la suivante :
func reservedRegions(
kind: ReservedRegion.Kind,
options: ReservedRegion.QueryOptions = [],
layoutDirectionBehavior: LayoutDirectionBehavior = .mirrors
) -> [ReservedRegion]
Elle ne renvoie que les régions qui chevauchent votre vue, avec des frames dans l'espace de coordonnées de votre vue. Si une région ne chevauche votre vue que partiellement, son frame peut commencer à des coordonnées négatives ou dépasser la taille de votre vue.
Le Tech Talk mentionne aussi onGeometryChange comme autre moyen d'obtenir un geometry proxy. Comme ReservedRegion est Equatable, vous pouvez observer les régions et les stocker dans un état. Voici notre ébauche de ce modèle, et non un exemple de code d'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, appelez reservedRegions(kind:) sur une UIView et lisez le frame de chaque région :
let regions = view.reservedRegions(kind: .division)
let frames = regions.map(\.frame)
Si vous devez réagir à l'angle de la charnière lui-même plutôt qu'à l'espace qu'elle occupe, consultez les états de charnière de l'iPhone Duo et onHingeChange.
Quand la région de division du pli est-elle active ?
Le pli n'est pas toujours un problème. Lorsque l'iPhone Duo est ouvert à plat, l'écran est continu et le contenu peut traverser le milieu. La région de division s'active et se désactive donc selon la position.
| Position | Région de division du pli | Renvoyée par défaut ? |
|---|---|---|
| Complètement ouvert, à plat | Inactive | Non |
| Partiellement ouvert, comme un livre | Active, verticale | Oui |
| Partiellement ouvert, comme un ordinateur portable | Active, horizontale | Oui |
Sarun note que, par défaut, reservedRegions ne renvoie que les régions actives, et que la division du pli n'est active que lorsque l'appareil est plié. La documentation de ReservedRegion d'Apple dit la même chose : lorsque l'iPhone Duo est complètement ouvert, la méthode ne renvoie aucune région de division. La caméra interne fonctionne de la même façon, en tant que région d'occlusion active uniquement pendant l'utilisation de la caméra. La caméra externe est toujours active.
Pour obtenir aussi les régions inactives, passez .includeInactive :
GeometryReader { proxy in
let regions = proxy.reservedRegions(
kind: .division,
options: .includeInactive)
let foldIsActive = regions.contains { $0.isActive }
Text(foldIsActive ? "Folded" : "Flat")
}
Pourquoi vouloir une région inactive ? Apple donne deux raisons. Une région inactive possède toujours un frame : vous pouvez donc lui réserver de la place et éviter que votre mise en page ne saute lorsque quelqu'un plie l'appareil. Et vous pouvez en tirer des décisions générales, comme privilégier un nombre pair de colonnes dans une grille dès qu'une division existe. Le Tech Talk ajoute que la région du pli a une largeur nulle lorsque l'appareil est à plat : utilisez donc les régions inactives pour ce type de décisions, et non pour un espacement précis.
Que contient une ReservedRegion ?
Chaque région est une petite valeur dotée de cinq propriétés. Toutes sont listées dans la documentation d'Apple pour iOS 27.1.
| Propriété | Type | Ce qu'elle indique |
|---|---|---|
frame | CGRect | L'emplacement de la région, dans les coordonnées de votre vue et en points, marges incluses |
margins | EdgeInsets | L'espace supplémentaire autour de la zone réservée qui en tient le contenu interactif à l'écart |
isActive | Bool | Si la région affecte votre vue en ce moment |
kind | ReservedRegion.Kind | .occlusion ou .division |
id | ReservedRegion.ID | Un identifiant stable d'une requête à l'autre |
Trois détails passent facilement inaperçus. D'abord, (0, 0) correspond au coin supérieur de début (top-leading) de la vue depuis laquelle vous lisez la région, et non de l'écran. Lisez les régions dans la vue qui positionne votre contenu, pour que les coordonnées correspondent. Dans un Layout personnalisé, faites vos calculs à partir de zéro et n'ajoutez bounds.origin qu'au moment de placer chaque sous-vue.
Ensuite, le frame inclut déjà les marges : ne les ajoutez donc pas une seconde fois. Enfin, les frames sont mis en miroir par défaut pour les langues qui s'écrivent de droite à gauche. Si votre contenu ne s'inverse pas avec le sens de mise en page, passez layoutDirectionBehavior: .fixed pour obtenir des frames non inversés.
Pour vous donner un ordre de grandeur, la démo de Sarun sur l'écran externe montre deux régions d'occlusion actives : l'une de 37 × 37 points en (399, 29), l'autre de 84 × 170 points en (382, 0). Elles couvrent la caméra et la zone d'état voisine, dans le coin supérieur de fin (top trailing). Considérez-les comme un exemple tiré d'iOS 27.x, et non comme des constantes. Lisez les frames à l'exécution, car ils sont relatifs à votre vue et peuvent changer d'une version à l'autre. Pour l'aspect safe area du même problème, consultez les safe areas et marges de contenu de l'iPhone Duo.
Comment éloigner les boutons et le texte du pli ?
Lorsqu'une division est active, gardez chaque vue entièrement d'un seul côté. Comparez la largeur et la hauteur du frame pour savoir dans quel sens court le pli, puis dimensionnez vos panneaux en conséquence. Cette vue est adaptée de la documentation d'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 {
// Plié comme un ordinateur portable : empiler les panneaux.
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 {
// À plat, ou plié comme un livre : une seule mise en page.
SingleLayout()
}
}
}
}
L'espaceur transparent a exactement la taille de la division : rien ne se retrouve donc dans le pli. L'exemple complet d'Apple gère aussi le pli vertical, de type livre, avec un HStack. L'iPhone Duo n'a qu'un seul pli : lire .first suffit donc.
Quelques règles tirées des recommandations d'Apple sont utiles ici :
- Ne déplacez que le nécessaire. Les commandes qui sautent loin ou disparaissent sont difficiles à retrouver. Privilégiez de petits ajustements et déplacez ensemble les commandes liées.
- Laissez défiler le contenu défilant. Par défaut, les listes et les scroll views ne séparent pas leurs lignes autour du pli, et le Tech Talk indique que le contenu défilant s'adapte généralement de lui-même. Ne vérifiez la division que si une ligne devient difficile à lire ou à utiliser.
- Utilisez un nombre pair de colonnes. Dans une grille, un nombre pair de colonnes se divise proprement au niveau du pli.
- Préférez un conteneur. Si votre écran se compose de deux vues liées, ArrangementView en SwiftUI les garde de part et d'autre du pli sans que vous ayez à lire les régions vous-même.
Qu'impliquent les régions réservées pour la conception de jeux ?
Les jeux dessinent généralement leur propre interface : le système ne peut donc pas la déplacer à votre place. Une barre de vie, un bouton de tir ou un score qui traverse le pli correspond exactement au contenu personnalisé qu'Apple demande de vérifier.
La position sur table, pliée comme un ordinateur portable et posée sur une table, change la question de la mise en page. Les recommandations de design d'Apple, telles que résumées par le designer Blake Crosley, indiquent que la zone supérieure convient bien au contenu que l'on regarde à distance, et la zone inférieure aux commandes interactives. Les directives d'Apple demandent aussi aux jeux de remplir l'écran lorsque la position change, de préférer un changement de rapport d'aspect au letterboxing, et de garder des tailles de texte et de commandes cohérentes lors du redimensionnement.
Plusieurs jeux présentés sur AppleDuo sont construits autour de cette séparation. Dans Battlefleet Duo, votre flotte se trouve sur l'écran du bas tandis que les eaux ennemies se dressent devant vous, et deux joueurs peuvent s'affronter face à face de part et d'autre du pli. Greens: Mini-golf se plie comme un ordinateur portable : vous jouez sur la moitié inférieure, et la moitié relevée devient une caméra de caddie. Nous décrivons ces jeux d'après leurs fiches App Store ; nous ne savons pas quelles API ils utilisent en interne.
Pour votre propre jeu, quelques modèles découlent de l'API :
- Traitez le pli comme une jointure de votre HUD. Ancrez les commandes tactiles sur la moitié à plat et les informations d'état sur la moitié relevée, en utilisant le frame de la division comme frontière.
- Gardez dégagés les éléments importants de l'aire de jeu. Un décor peut traverser le pli, mais pas une cible, une carte ou une tuile que l'on doit toucher.
- Prévoyez les deux orientations. Un pli de type livre est vertical, ce qui convient à une séparation comme deux joueurs ou deux plateaux côte à côte. Un pli de type ordinateur portable est horizontal.
- Évitez les sauts de mise en page. Interrogez avec
.includeInactiveet réservez l'espace à l'avance si un décalage soudain risque de gâcher la partie.
D'autres exemples sont disponibles sur notre page Built for the Fold.
À retenir
- Les régions réservées, nouvelles dans iOS 27.1, signalent les zones que votre interface ne doit pas utiliser. Sur l'iPhone Duo, il s'agit de la caméra externe, de la caméra interne lorsqu'elle est active, et du pli.
- Appelez
proxy.reservedRegions(kind: .division)pour le pli ou.occlusionpour les caméras. UIKit propose la même méthode surUIView. - La division du pli n'est active que lorsque l'iPhone Duo est partiellement plié. Passez
.includeInactivepour l'obtenir à plat, et vérifiezisActive. - Chaque
ReservedRegionpossède unframedans les coordonnées de votre vue, en points,marginsdéjà incluses. Lisez-le dans la vue qui place votre contenu. - Les conteneurs standard gèrent déjà le pli. Utilisez les régions réservées pour les commandes personnalisées, les overlays et les HUD de jeu, et gardez tout élément tactile d'un seul côté du pli.
Ensuite, découvrez comment ArrangementView gère le pli dans les mises en page à deux vues, ou parcourez la checklist de préparation de votre app pour l'iPhone Duo.
Questions fréquentes
Que sont les régions réservées sur l'iPhone Duo ?
Les régions réservées sont des zones de l'écran que le matériel se réserve : votre contenu doit donc les éviter. Sur l'iPhone Duo, il y en a trois : la caméra externe, la caméra interne lorsqu'elle est utilisée, et le pli.
Comment obtenir le pli de l'iPhone Duo en SwiftUI ?
Enveloppez votre contenu dans un GeometryReader et appelez proxy.reservedRegions(kind: .division). Le pli est renvoyé sous forme de ReservedRegion dont le frame est exprimé dans l'espace de coordonnées de votre vue, en points, marges déjà incluses.
Pourquoi reservedRegions renvoie-t-il un tableau vide sur un iPhone Duo à plat ?
Par défaut, la méthode ne renvoie que les régions actives, et la région de division du pli est inactive lorsque l'iPhone Duo est complètement ouvert. Passez options: .includeInactive pour l'obtenir malgré tout, puis vérifiez isActive sur chaque région.
Quelle est la différence entre les régions division et occlusion ?
Une région d'occlusion recouvre une partie de votre vue, comme une caméra ou la Dynamic Island : vous en écartez donc le contenu. Une région de division sépare votre vue en plusieurs parties, comme le pli : vous disposez donc le contenu de part et d'autre.
Ai-je besoin des régions réservées si j'utilise des vues SwiftUI standard ?
En général, non. Apple indique que les split views, barres d'onglets, alertes, menus contextuels et feuilles s'adaptent déjà au pli et aux caméras. Vérifiez les régions réservées dans les overlays personnalisés, les commandes flottantes et les vues que vous positionnez avec des frames explicites ou un Layout personnalisé.
Sources
- 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
Faites du pli une partie de votre app.
Nous présentons les apps et les jeux qui exploitent vraiment l’iPhone Duo. Envoyez-nous la vôtre avec un lien vers l’App Store, ou découvrez ce que d’autres ont créé.