Préparer votre app pour l'iPhone Duo : un exemple complet
Comment préparer une app pour l’iPhone Duo ? Compilez-la avec le SDK iOS 27.1, faites-lui parcourir chaque position dans le simulateur, corrigez ce que ce parcours révèle et organisez la soumission autour de deux dates qu’Apple n’a pas encore annoncées. L’iPhone Duo sera en vente le 23 octobre, sous iOS 27.1.1 Ce qu’une app obtient sur cet appareil dépend de la version du SDK inscrite dans son binaire : un même fichier source, lié en 26.0, en 27.0 puis en 27.1, est apparu sous la forme d’une boîte de la taille d’un téléphone, d’une fenêtre à côté du bandeau d’état, puis de l’écran entier, avec ses barres sur le côté et la pliure signalée.12 Au 2 octobre, seules les bêtas d’Apple inscrivent 27.1 ou plus (Xcode 27.1 beta, qui contient le simulateur du Duo, et Xcode 27.2 beta), et App Store Connect accepte leurs builds pour TestFlight, pas pour la boutique.8 Ce billet mène tout le travail sur Kiradex, une app de collection de cartes à échanger que nous avons dans TestFlight : ce qui est venu gratuitement, ce que le parcours a repéré et que la lecture du code n’avait pas vu, les captures d’écran pour les deux écrans, et un brief à confier à un agent de code.
L’essentiel
- Le tampon du SDK est l’interrupteur. iOS lit la version du SDK dans le
LC_BUILD_VERSIONdu binaire. Tamponnée 27.1, l’app sonde a obtenu l’écran entier, 466 par 678 points fermée et 951 par 669 ouverte, avec des barres verticales et des régions réservées. Tamponnée 27.0, elle s’arrêtait à 80 points du bord où se trouve le bandeau d’état, gardait des barres horizontales et ne savait rien de la pliure. Tamponnée 26.0, c’était un téléphone de 375 par 667 dans une boîte. Vérifiez la vôtre avecotool -l.12 - Le calendrier compte deux dates inconnues. TestFlight accepte les builds du SDK 27.1 depuis le 18 septembre et ceux de la bêta 27.2 depuis le 16 septembre ; l’App Store n’accepte que les builds du SDK 27.0 ; les tailles de captures du Duo sont publiées, et leur téléversement « will be available later this year » (sera possible plus tard dans l’année).89 Une clé d’écran de lancement est désormais exigée au téléversement.10
- Les conteneurs système ont fait l’essentiel. Un
TabView, unNavigationStackdans quatre de ses cinq onglets et des éléments de barre d’outils dotés d’un titre et d’un symbole ont placé les barres de Kiradex sur le côté sans une ligne de code propre au Duo. Une seuleArrangementViewa scindé l’écran ouvert et déplacé son séparateur sur la pliure en position Book. Un seulonHingeChangerejoue l’ouverture de l’app quand le téléphone se déplie.13 - Le parcours a trouvé ce que la lecture avait manqué. Une feuille dont le seul bouton est un « Done » textuel réserve le bandeau latéral et le laisse vide. La carte plein écran passe sous la caméra externe. Pivotée en portrait, la vue scindée s’empile. Une carte restée ouverte pendant le dépliage atterrit dans la mise en page compacte, étirée. La mise en page en largeur regular, écrite pour l’écran interne, se casse sur un iPhone de 6,9 pouces en paysage.13
- Tant que la boutique n’accepte pas 27.1, une même arborescence de sources a besoin de deux Xcode.
#availablen’y peut rien ; le SDK 27.0 ne contient aucuneArrangementViewcontre laquelle compiler. Une condition de compilation, ou#if canImport(SwiftUI, _version: 8.0.85), isole les nouveaux appels.14 - Les captures sortent de la même exécution. Les captures du simulateur ont exactement les tailles d’App Store Connect, tout comme les ouvertures des contours du Duo fournis par Apple. Les règles d’Apple exigent toujours une vue de face, sans retouche, et aucun rendu 3D de l’appareil.911
Où en sont les choses au 2 octobre
| État | Date | |
|---|---|---|
| Le téléphone | Précommandes le 16 octobre, en vente le 23 octobre, « available with iOS 27.1 » (disponible avec iOS 27.1)1 | 9 septembre |
| Le SDK | Xcode 27.1 beta (27A9269) contient le SDK iOS 27.1 et le simulateur de l’iPhone Duo ; le flux Releases d’Apple ne mentionne ni deuxième bêta 27.1 ni version candidate. Xcode 27.2 beta contient les mêmes API et aucun simulateur du Duo814 | 18 septembre ; flux lu le 2 octobre |
| TestFlight | Ouvert aux builds de Xcode 27.1 beta et des bêtas de Xcode 27.2, en interne comme en externe8 | 16, 18 et 28 septembre |
| App Store | Ouvert aux builds de Xcode 27 et du SDK 27.0. Aucune entrée ne l’ouvre au SDK 27.18 | 14 septembre |
| Captures du Duo | Tailles publiées ; le téléversement « will be available later this year » (sera possible plus tard dans l’année)9 | 9 septembre |
| Écran de lancement | Exigé au téléversement pour tout ce qui est compilé avec le SDK iOS 27 ou plus récent10 | Note technique révisée le 14 septembre |
Trois de ces lignes attendent Apple, et aucune ne bloque le travail. L’ordre qui découle du tableau : passer l’app au SDK 27.1 et la lancer dans le simulateur, lui faire parcourir chaque position, corriger ce que le parcours révèle, mettre ce build dans TestFlight, et tenir prêtes la soumission à la boutique et les captures du Duo pour le jour où chacune ouvrira.
Le point de départ d’Apple est le premier de ses six Tech Talks, long de dix minutes, et tout ce qui suit le suppose connu :
Première étape : le tampon du SDK décide de ce que le téléphone vous donne
La présentation s’ouvre sur une promesse de compatibilité en trois niveaux. Une app qui n’a pas été compilée avec le SDK iOS 27 fonctionne quand même : « When the device is closed, your app will use the screen space to the left of the status bar and camera. When the device is open, your app will be a familiar size and aspect ratio. » (Fermé, l’app occupe l’espace à gauche de la barre d’état et de la caméra ; ouvert, elle garde une taille et des proportions familières.) (0:36) Une app qui a adopté le SDK iOS 27 « will extend to the left of the status bar area on the inner display. » (s’étendra, sur l’écran interne, jusqu’à la gauche de la zone de la barre d’état.) (0:58) Puis : « When you build your app with the iOS 27.1 SDK, your app extends to the edge of the screen. Standard navigation and toolbar buttons now lay out vertically under the status bar. » (Compilée avec le SDK iOS 27.1, l’app s’étend jusqu’au bord de l’écran, et les boutons standard de navigation et de barre d’outils se disposent verticalement sous la barre d’état.) (1:05)3
Ces niveaux ne sont pas une propriété de votre code. Ils sont la propriété d’un seul nombre dans votre binaire, la version du SDK que l’éditeur de liens consigne dans la commande de chargement LC_BUILD_VERSION, et iOS la lit au lancement. Pour mesurer ce qui en dépend, j’ai écrit une petite app sonde, un TabView contenant un NavigationStack avec une barre d’outils de cinq éléments et une ArrangementView, compilée trois fois à partir du même fichier source. La seule différence entre les trois binaires est ce nombre : 26.0, 27.0, 27.1. Puis j’ai lancé les trois dans le simulateur de l’iPhone Duo, dans chaque position.12

Un fichier source, trois tampons de SDK, ouvert et à la verticale. De gauche à droite : 26.0, 27.0, 27.1.
| Position | Tampon 26.0 | Tampon 27.0 | Tampon 27.1 |
|---|---|---|---|
| Fermé | 375 par 667, mis à l’échelle dans l’espace à côté du bandeau | 386 par 678, à côté du bandeau | 466 par 678, l’écran entier |
| Ouvert | 375 par 667, un téléphone au milieu de l’écran | 871 par 669 | 951 par 669 |
| Ouvert, pivoté | 375 par 667 | 669 par 871 | 669 par 951 |
| Fermé, pivoté | 667 par 375 | 678 par 386 | 678 par 466 |
| Classe de taille en largeur, ouvert | compact | regular | regular |
| Barres | horizontales partout | horizontales partout | verticales, sauf ouvert et pivoté |
toolbarVerticalEdge |
nil | nil | trailing, sauf ouvert et pivoté, où il vaut nil |
| Régions réservées | aucune | aucune | la pliure, les deux caméras, la colonne d’état |
| Partiellement plié | aucun changement | aucun changement | la pliure devient une division active ; les arrangements scindés y ouvrent un espace |
Tailles de fenêtre en points, telles que la fenêtre de chaque build les a elle-même signalées.12
Lisez deux fois la colonne du milieu, car c’est celle avec laquelle la plupart des apps s’apprêtent à sortir. Un build issu de Xcode 27 obtient la largeur regular sur l’écran interne et la majeure partie de l’écran, un vrai progrès par rapport au téléphone en boîte de la première colonne. Il s’arrête pourtant à 80 points du bord arrière, là où se trouve le bandeau d’état, il n’obtient pas de barres verticales, et le système ne lui dit rien de la pliure ni des caméras : chaque requête de régions réservées est revenue vide, dans chaque position, quel que soit le nombre de fois où l’app sonde a posé la question.12 Pour m’assurer que le tampon était un substitut honnête, j’ai aussi compilé une version simple de l’app sonde avec Xcode 27.0 lui-même, contre son propre SDK iOS 27.0. Elle a obtenu les mêmes fenêtres : 386 par 678 fermée, 871 par 669 ouverte.12
Le guide écrit d’Apple est moins précis que la présentation sur ce point, et sa formulation a changé. Le 17 septembre, sa vue d’ensemble disait « Build your app with Xcode 27.1 or later to use all of the available screen space on iPhone Duo. In earlier versions, your app doesn’t extend under the status bar and camera. » (Compilez avec Xcode 27.1 ou plus récent pour utiliser tout l’espace disponible ; dans les versions antérieures, l’app ne s’étend pas sous la barre d’état et la caméra.) Le 19 septembre, elle disait, comme encore au 2 octobre, « Build your app with the latest version of Xcode to use all of the available screen space on iPhone Duo. When you build with Xcode 26 and earlier, your app doesn’t extend under the status bar and camera. » (Compilez avec la dernière version de Xcode pour utiliser tout l’espace ; avec Xcode 26 ou antérieur, l’app ne s’étend pas sous la barre d’état et la caméra.)2 La nouvelle phrase ne désigne comme insuffisants que Xcode 26 et les versions antérieures, et « latest version » (dernière version) ne dit pas si une bêta compte ; un lecteur pourrait donc croire qu’un build de Xcode 27.0 obtient l’écran entier. Dans le simulateur de cette bêta, ce n’est pas le cas. Il obtient le niveau intermédiaire de la présentation, et c’est l’ancienne formulation qui correspondait à mes mesures. Tant que le matériel ne dit pas le contraire, planifiez d’après le tableau.
Avant toute chose, vérifiez donc le tampon du build que vous testez :
otool -l Build/Products/Debug-iphonesimulator/YourApp.app/YourApp | grep -A4 LC_BUILD_VERSION
Un build de débogage issu de Xcode garde son code dans YourApp.debug.dylib, à côté d’un petit lanceur, et les deux portent la commande. Vous cherchez sdk 27.1 ou plus ; l’app sonde tamponnée 27.2, la valeur qu’écrirait le SDK de la bêta de Xcode 27.2, a reçu le même traitement que 27.1.12 Celle de Kiradex indique minos 27.0 et sdk 27.1 : l’app s’installe sous iOS 27.0 et obtient le comportement de 27.1 sur un Duo.13
J’insiste sur ce point parce que je m’y suis trompé publiquement. Mon premier compte rendu sur ce simulateur, le 21 septembre, affirmait que la barre d’outils ne devenait jamais verticale et que les régions réservées étaient vides dans chaque position. La bêta n’y était pour rien. J’avais compilé cette app sonde en appelant directement swiftc -sdk, l’étape d’édition de liens a pris pour racine le SDK macOS du même Xcode, et le binaire est sorti tamponné 27.0 : tout ce que j’ai mesuré ce jour-là, c’était la colonne du milieu. Ce billet porte désormais la correction.12 Si votre mise en page Duo semble à moitié adoptée dans le simulateur, avec des barres en travers du haut et une bande noire morte sur le côté, vérifiez le tampon avant de vérifier votre code.
L’app sur l’établi
Kiradex est une app de collection de cartes à échanger que nous avons dans TestFlight : chaque série, les cartes que vous possédez et celles que vous cherchez, leur valeur dans le temps, et chaque carte sous forme d’objet 3D que vous pouvez retourner. Elle est gratuite, réservée à l’iPhone, fonctionne sous iOS 27.0 et versions ultérieures, et conserve les listes d’un collectionneur dans son propre iCloud, sans aucun serveur à nous entre les deux.13 Elle n’est pas terminée. Le scanner n’a jamais rencontré de vraie caméra, et jusqu’à cette semaine personne n’avait regardé l’app sur un Duo ouvert : à côté de la mise en page pour l’écran interne, sa feuille de route portait la ligne « Seen on the open Duo’s inner display only by the column maths; the simulator was folded shut. » (Vue sur l’écran interne du Duo ouvert uniquement par le calcul des colonnes ; le simulateur était resté fermé.)13 Cela en fait un test honnête. Le travail Duo qu’elle contient a été écrit d’après la documentation d’Apple et jamais vérifié sur un écran.
Ce qu’elle fait pour le Duo est modeste, et mérite d’être énuméré justement parce que si peu relève du code propre au Duo :
- La navigation appartient au système. Un
TabViewà cinq onglets, dont un avec le rôle de recherche, et unNavigationStackdans quatre d’entre eux ; le scanner est une vue caméra sans barre propre. Les éléments de barre d’outils sont desLabelavec un titre et un symbole, attachés par.toolbar. Il n’y a de barre personnalisée nulle part. - La mise en page suit la classe de taille. La largeur compact reçoit une page de classeur à trois colonnes et pousse l’inspecteur d’une carte sur la pile. La largeur regular, qui pour une app réservée à l’iPhone désigne surtout l’écran interne du Duo, reçoit un mur de cartes en nombre pair de colonnes ; en choisir une partage l’écran entre la page et l’inspecteur.
- Deux appels issus du SDK 27.1. Le partage est une
ArrangementViewde style.split, avec unHStackcomme solution de repli sous iOS 27.1. EtonHingeChangerejoue l’animation d’ouverture de l’app, un appareil rouge qui s’ouvre, quand le téléphone passe de fermé à n’importe quel autre état. - Aucun verrouillage d’orientation, et un écran de lancement.
Info.plistliste le portrait et les deux paysages, et déclareUILaunchScreen.13
C’est toute la liste : deux vérifications de disponibilité dans deux fichiers. Tout le reste de ce que le téléphone fait à l’app, il le fait à n’importe quelle app construite de cette façon.
Les images de ce billet montrent l’app telle qu’elle tourne, avec des visuels de cartes issus du catalogue public qu’elle lit. Kiradex est un outil indépendant pour collectionneurs, sans lien avec Nintendo, Creatures Inc., GAME FREAK inc. ou The Pokémon Company ni approuvé par eux, et les visuels des cartes appartiennent à leurs propriétaires.
Deuxième étape : parcourir chaque position
Le guide d’Apple présente le parcours sous forme de quatre vérifications :2
- « Confirm your views resize well in each supported orientation and pose. » (Vérifiez que vos vues se redimensionnent bien dans chaque orientation et position prises en charge.)
- « Inspect how the system presents your app’s navigation bars, toolbars, and tab bars vertically on the side of the display. » (Examinez comment le système présente verticalement, sur le côté de l’écran, les barres de navigation, barres d’outils et barres d’onglets de votre app.)
- « Identify any views, sheets, or popovers that position awkwardly when you fold or open iPhone Duo. » (Repérez les vues, feuilles ou popovers qui se placent mal quand vous pliez ou ouvrez l’iPhone Duo.)
- « Identify elements or controls in your views that appear in the fold, and are difficult to see or interact with. » (Repérez les éléments ou commandes qui tombent dans la pliure et deviennent difficiles à voir ou à manipuler.)
Ses recommandations de conception disent combien de mises en page cela devrait demander : « A compact width layout for the outer display and a regular width layout for the inner display give you the fundamentals for every pose. » (Une mise en page en largeur compact pour l’écran externe et une en largeur regular pour l’écran interne vous donnent les bases de chaque position.)7
Les positions sont des boutons dans Device Hub : Closed, Book, Open et Rotate Right, et chaque combinaison donne un écran différent. Le guide de SwiftLee ajoute un réglage plus fin dont je n’ai pas eu besoin : « Holding Option ⌥ reveals a slider that you can use to control the hinge angle of the device with precision » (Maintenir la touche Option ⌥ fait apparaître un curseur qui permet de régler précisément l’angle de la charnière).17 Avant de regarder l’app, il est utile de savoir ce que le système remet à n’importe quelle app dans chacune. Voici les relevés de l’app sonde avec le tampon 27.1 :12
| Position | Fenêtre, points | Classes de taille (largeur, hauteur) | Barres | Régions réservées signalées |
|---|---|---|---|---|
| Fermé | 466 par 678 | compact, regular | verticales, bord arrière | caméra externe, 37 par 37, active ; colonne d’état, 84 par 170, active |
| Fermé, pivoté | 678 par 466 | compact, compact | verticales, bord arrière | caméra externe, active ; zone d’état, 84 par 82, active |
| Ouvert | 951 par 669 | regular, regular | verticales, bord arrière | pliure, 40 de large de x 455 à 495, inactive ; caméra interne, 58 par 37, inactive ; colonne d’état, 84 par 120, active |
| Book | 951 par 669 | regular, regular | verticales, bord arrière | les trois mêmes, pliure active |
| Ouvert, pivoté | 669 par 951 | regular, regular | horizontales | pliure, 40 de haut de y 455 à 495, inactive ; caméra interne, inactive ; zone d’état, 134 par 82, active |
| Book, pivoté | 669 par 951 | regular, regular | horizontales | les trois mêmes, pliure active |
Trois éléments de ce tableau ont façonné tout ce qui a suivi.
La fenêtre ne change pas quand le téléphone se plie. Book et Open signalent la même taille. La seule différence que l’app peut voir, c’est que la division de la pliure passe d’inactive à active, et que la charnière se déclare partiellement ouverte à 127 degrés là où elle se déclarait entièrement ouverte à 180. Une app qui ne lit que sa taille n’apprend jamais que le téléphone a été plié.
La pliure est toujours là, et elle est étroite. Elle est signalée ouvert comme plié, pile au milieu, et le cadre que renvoie l’API mesure 40 points de large dans les deux états, avec 20 points de marge de chaque côté. La présentation d’Apple dit de la région de la pliure : « When flat, it’s inactive and has a width of zero. » (À plat, elle est inactive et sa largeur est nulle.) (7:32) Le simulateur ne renvoie pas de cadre de largeur nulle. Les notes de terrain d’Artem Novichkov décrivent le même relevé comme « 40 pt wide, with 20 pt margins on each side of a zero-width fold line, » (40 pt de large, avec 20 pt de marge de chaque côté d’une ligne de pliure de largeur nulle)17 et je lis le zéro de la présentation de la même façon, comme la ligne entre les marges ; c’est une lecture, pas ce que dit le texte d’Apple. La présentation fait aussi la remarque pratique : « By default, only active ones will be returned, but you can query for inactive ones » (Par défaut, seules les régions actives sont renvoyées, mais vous pouvez demander les inactives) et « in grid-like layouts, you could prefer even numbers of columns when a division region is present regardless of its active state. » (Dans les mises en page en grille, vous pouvez préférer un nombre pair de colonnes dès qu’une région de division est présente, qu’elle soit active ou non.) (7:16, 7:41)5
Les régions arrivent tard. À chaque lancement, les premières évaluations de l’app sonde ne lisaient aucune région, et toutes les évaluations suivantes lisaient l’ensemble complet. Une vue qui pose la question une seule fois, lors de sa première passe de mise en page, met en cache un tableau vide. Lisez-les dans le body de la vue, à chaque évaluation ; l’app sonde se réévaluait sur un minuteur d’une seconde, et les notes d’Artem Novichkov énoncent la règle sans détour : « Read them in the GeometryReader body so the view updates when they arrive. Don’t cache them. » (Lisez-les dans le body du GeometryReader pour que la vue se mette à jour à leur arrivée. Ne les mettez pas en cache.)1217
Une remarque pratique avant l’app. Le runtime de simulateur iOS 27.1 de cette bêta prend en charge un seul type d’appareil, l’iPhone Duo ; lui demander un iPhone 18 Pro Max échoue avec « Incompatible device ». La comparaison ci-dessous, le même build sur un iPhone ordinaire, a donc tourné sur le runtime iOS 27.0, ce qui est aussi un moyen rapide de confirmer que les solutions de repli #available fonctionnent.12

Un seul build de Kiradex sur un iPhone de 6,9 pouces, le Duo fermé et le Duo ouvert. Rien dans le code de l’app ne place les barres sur le côté.
Ce que le parcours a trouvé
Un test d’interface a fait passer le build 5 par huit types d’écran dans chacune des six positions (sept avec le téléphone fermé et pivoté, où le bouton Réglages était passé dans le menu de débordement), pendant qu’un script capturait les deux écrans à chaque arrêt : 1398 par 2034 pixels à l’extérieur, 2853 par 2007 à l’intérieur, les tailles qu’indique App Store Connect.13 À l’aune des quatre vérifications d’Apple, l’app a réussi plus de points que je ne l’attendais et a échoué à des endroits qu’aucune lecture du code n’avait signalés.
Ce qui est venu gratuitement
Les barres. Fermé, la barre d’outils et les cinq onglets se dressent dans le bandeau sous l’horloge ; ouvert, de même ; ouvert et pivoté, ils retournent en haut et en bas. Rien dans l’app ne le demande. La deuxième présentation explique pourquoi les barres faites main restent à la traîne : « When used to build custom bars, content from sub-components like UIToolbar, UINavigationBar, or UITabBar won’t be considered. » (Quand on s’en sert pour construire des barres personnalisées, le contenu de sous-composants comme UIToolbar, UINavigationBar ou UITabBar n’est pas pris en compte.) (2:52)4 Et comme chaque élément de barre d’outils des écrans principaux est un Label, chacun a un symbole pour le bandeau et un titre pour le menu de débordement, ce qui est l’autre condition du guide : « If your item has a title and doesn’t have an icon, the system doesn’t present it vertically. » (Si votre élément a un titre mais pas d’icône, le système ne le présente pas verticalement.)2
La pliure. Ouvert, les cartes d’une série s’alignent par six, un nombre pair, si bien qu’aucune carte ne se trouve au milieu de l’écran. Choisissez-en une, et l’écran se partage entre la page et l’inspecteur de la carte au milieu de la zone de contenu de l’app, à x 433. C’est 42 points à gauche de la pliure, parce que le bandeau retire 84 points sur le côté droit, et tant que le téléphone est à plat, cela n’a aucune importance. En position Book, la vue d’arrangement déplace le séparateur sur la pliure et laisse vide la bande de 40 points : l’inspecteur qui commençait à x 433 commence maintenant à 495. L’app n’a aucun code pour la position Book ; c’est ArrangementView qui fait ce que décrit la présentation, « moving, resizing, or reorganizing what’s already there. » (déplacer, redimensionner ou réorganiser ce qui est déjà là.) (6:04)513

Ouvert et à plat, puis en position Book. L’espace dans la seconde image est la pliure, et ce n’est pas l’app qui l’a placé là.
Les feuilles, une fois ouvert. Sur l’écran interne, une feuille arrive centrée et son bouton Done reste horizontal ; en position Book, la feuille de l’app sonde s’est déplacée d’elle-même du côté leading (le côté de tête) de la pliure.12
La charnière, en tant qu’événement. Dépliez le téléphone pendant que l’app tourne et son ouverture se rejoue sur l’écran interne : l’appareil rouge, fermé, puis s’ouvrant sur l’app. C’est un seul gestionnaire onHingeChange qui se déclenche quand l’état quitte closed, et c’est exactement la répartition des rôles que demande la quatrième présentation : « Hinge data is observed live, and is ideal for driving interactions or effects. For layout, use the arrangement and region APIs. » (Les données de charnière s’observent en direct et conviennent parfaitement pour piloter des interactions ou des effets ; pour la mise en page, utilisez les API d’arrangement et de régions.) (2:34)6

Dépliage avec l’app en cours d’exécution : l’ouverture est l’appareil propre à l’app, dessiné par l’app, rejoué par la charnière.
Ce qui lui a échappé
Une feuille avec un seul bouton textuel réserve le bandeau et le laisse vide. Fermé, la feuille Réglages cède le long de son bord arrière une bande pour une barre verticale, puis n’y met rien : le seul élément de barre d’outils est un « Done » doté d’un titre et sans symbole, et un élément purement textuel reste horizontal. Le formulaire est comprimé dans ce qui reste. L’app sonde a mesuré le coût : 374 points de largeur de contenu avec le bandeau réservé, 450 avec la barre verticale désactivée.12 La présentation d’Apple nomme précisément ce cas : « if a sheet is control-heavy with only one item, like the close button here, consider disabling a vertical bar so it doesn’t reduce available space. » (Si une feuille est chargée en commandes avec un seul élément, comme ce bouton de fermeture, envisagez de désactiver la barre verticale pour ne pas réduire l’espace disponible.) (14:37)4 Il existe deux réparations, et l’app sonde a essayé les deux. Donnez un symbole au bouton, Button("Done", systemImage: "checkmark"), et il passe dans le bandeau sous forme de coche mise en avant ; ou ajoutez .toolbarVerticalBehavior(.disabled) au contenu de la feuille, et le bandeau disparaît, au prix d’une feuille plus courte.

De gauche à droite : la feuille de l’app, puis l’app sonde avec un Done purement textuel, avec un symbole, et avec la barre verticale désactivée.
La carte plein écran passe sous la caméra. La pièce maîtresse de l’app est une carte sur une scène noire, barres masquées, et sa scène ignore la zone sûre sur tous les bords. Sur l’écran externe, cela envoie le coin supérieur de la carte sous la caméra. Le système signale cette caméra à toute vue qui le demande, sous forme d’occultation active de 37 points de côté, et sa position correspond à un point et demi près à la découpe des visuels de contour d’Apple.1112 Les recommandations de conception d’Apple autorisent le traitement pleine largeur « as long as nothing conflicts with the Dynamic Island or the status bar. » (tant que rien n’entre en conflit avec la Dynamic Island ou la barre d’état.)7 La réparation consiste à garder le fond noir à fond perdu et à ramener la carte elle-même à l’intérieur : soit en laissant la scène respecter la zone sûre arrière et supérieure sur cet écran, soit en lisant reservedRegions(kind: .occlusion) et en cadrant la carte à l’écart de ce qui est renvoyé.

La capture de la visionneuse dans le contour d’Apple pour l’écran externe. La capture du simulateur n’a pas de trou ; le téléphone, si.
Pivotés, les deux volets s’empilent. Ouvert et pivoté en portrait, l’écran mesure 669 points de large et reste en largeur regular, donc l’app continue de partager. Mais une vue d’arrangement qui remplit un espace plus haut que large partage en haut et en bas, selon le guide d’Apple : « it places the primary view on top and the secondary view below it when the containing view is taller than it is wide. » (elle place la vue principale en haut et la vue secondaire en dessous quand la vue conteneur est plus haute que large.)2 Le résultat est une bande qui montre une rangée de cartes et le haut d’une deuxième, au-dessus d’un inspecteur. Le commentaire de l’app sur cette ligne précise que la paire « is only useful side by side, » (n’est utile que côte à côte), et rien ne l’imposait. Restreindre le style avec .split.axes(.horizontal) est la commande documentée,16 avec un piège que la présentation détaille : « If the split arrangement cannot split among an axis, and it’s the primary axis, the arrangement view chooses to only show a single view. » (Si l’arrangement scindé ne peut pas partager le long d’un axe et qu’il s’agit de l’axe principal, la vue d’arrangement choisit de n’afficher qu’une seule vue.) (12:44)5 L’app sonde confirme les deux moitiés : en remplissant l’écran pivoté, un partage simple s’est empilé, et le partage limité à l’horizontale a montré le volet principal et rien d’autre.12 Pour cette app, cela masquerait l’inspecteur ; la correction honnête est donc une décision, pas un modificateur : quand l’espace est plus haut que large, poussez l’inspecteur sur la pile comme le fait la mise en page compacte.

Pivoté : des barres horizontales, comme le prévoient les recommandations d’Apple, et un partage parti dans le mauvais sens pour cette paire de vues.
Une carte restée ouverte pendant le dépliage n’atterrit dans aucune des deux mises en page. Fermé, choisir une carte pousse son inspecteur sur la pile de navigation. Dépliez alors que cet inspecteur est affiché, et la carte est toujours là, ce qui est la partie facile à rater. Mais c’est toujours un écran poussé, désormais large de 951 points : la scène à gauche, les détails dans une boîte blanche à la dérive sur le noir, un bouton Retour dans le bandeau. Ce que l’app prévoit pour cet écran, c’est le mur avec la carte à côté, et le seul moyen d’y parvenir est de revenir en arrière et de choisir à nouveau la carte. Une même sélection pilote les deux mises en page ; un même chemin de navigation, non. La réparation consiste à détecter le passage de la largeur compact à la largeur regular avec une carte sélectionnée et à retirer l’écran poussé, pour que le partage prenne le relais.

La même carte avant et après le dépliage. L’état a survécu ; la mise en page est la compacte, étirée.
La largeur regular n’est pas « le Duo ». L’app traite la largeur regular comme l’écran interne : mur, colonnes en nombre pair, partage. Un iPhone de 6,9 pouces couché sur le côté est lui aussi en largeur regular, avec une hauteur compact, et l’app ne verrouille pas l’orientation. Exécutée là, la même branche produit une page en retrait du bord gauche, un inspecteur dont la colonne de détails est trop étroite pour le nom de la carte, et des boutons d’action coupés au bas de l’écran. Rien de tout cela n’est nouveau dans iOS 27, et cela n’est apparu dans aucune position du Duo que j’ai testée ; le travail sur le Duo l’a mis au jour parce que c’était la première fois que quelqu’un parcourait la mise en page en largeur regular sur chaque écran qui la signale. Ce qui distingue les deux cas, c’est l’autre classe de taille : l’écran interne est regular dans les deux dimensions, et la présentation d’Apple donne l’écran externe couché sur le côté comme compact dans les deux.3 Une mise en page qui a besoin de place dans deux directions devrait interroger les deux.

La mise en page en largeur regular sur un téléphone qui n’est pas un Duo : un iPhone de 6,9 pouces couché, iOS 27.0.
Le clavier recouvre le bandeau. Clavier affiché sur l’écran externe, les onglets du bas du bandeau passent derrière. C’est la mise en page du système, pas un défaut ; la présentation dit que la barre peut devoir déborder « as other competing UI appears, like the keyboard » (à mesure qu’apparaissent d’autres éléments d’interface concurrents, comme le clavier) (11:50).4 Il figure sur cette liste parce qu’il a cassé l’outillage : mon premier parcours a touché « Collection » avec le clavier de recherche affiché, et le toucher est tombé sur la lettre P. Les tests d’interface qui supposent qu’une barre d’onglets est toujours accessible échouent ici en premier.
Deux points plus mineurs. L’app choisit un nombre pair de colonnes d’après la classe de taille en largeur, là où la présentation suggère de se fier à la région propre de la pliure, présente ou non. Et un point qui n’a rien à voir avec le pliage : ouverte quatre fois de suite sur le simulateur de 6,9 pouces, la visionneuse plein écran a montré la carte la première fois et un écran noir vide les trois suivantes. Ni l’un ni l’autre ne bloque un build TestFlight. Tous deux sont restés invisibles jusqu’à ce que l’app soit sur un écran et que quelque chose appuie sur ses boutons dans l’ordre.
Ce que le simulateur ne pouvait pas montrer
Le scanner. Il ouvre la caméra grand-angle arrière et utilise déjà un coordinateur de rotation, ce que demande la présentation consacrée à la caméra : « On iPhone Duo, the rotation coordinator will update when your app moves displays. » (Sur l’iPhone Duo, le coordinateur de rotation se met à jour quand votre app change d’écran.) (8:19)6 Savoir si la session survit au passage d’un écran à l’autre est une question pour le matériel ; le simulateur n’a aucune caméra. Les notes de version d’Apple ajoutent StandBy et la plupart des extensions d’app à ce que ce runtime ne peut pas exécuter, et les notes de Xcode 27.2 beta 2 en ajoutent une pour quiconque automatise les captures : « Screenshots and recordings in iPhone Duo may be black for up to a few minutes after booting the device. » (Les captures et enregistrements dans l’iPhone Duo peuvent rester noirs jusqu’à quelques minutes après le démarrage de l’appareil.)20
Une arborescence de sources, deux Xcode
Le calendrier crée un problème. Le build qu’accepte la boutique vient de Xcode 27 et du SDK 27.0 ; le build qui se comporte correctement sur l’iPhone Duo vient du SDK 27.1. Tant qu’Apple n’ouvre pas la boutique au second, une app qui veut publier une mise à jour tout en continuant de travailler sa mise en page Duo doit compiler avec les deux.
if #available(iOS 27.1, *) ne suffit pas. La disponibilité est une question d’exécution ; le compilateur doit tout de même trouver le symbole. Kiradex enveloppe ses deux appels Duo exactement de cette façon, et sa cible de déploiement est 27.0, si bien que le build s’installe sur un téléphone qui n’a pas été mis à jour. Avec le SDK 27.1, cela compile. Avec Xcode 27.0, un fichier qui fait la même chose s’arrête sur error: cannot find 'ArrangementView' in scope, parce que le SDK 27.0 ne contient pas ce type.14 Kiradex n’est pas encore sur la boutique, il peut donc simplement rester sur la chaîne d’outils bêta ; une app qui a des clients ne le peut pas.
Les conditions documentées de Swift ne distinguent pas non plus les deux SDK. #if compiler(>=6.4) est vrai dans les deux cas : Xcode 27.0, Xcode 27.1 beta et Xcode 27.2 beta affichent tous le même Apple Swift version 6.4 (swiftlang-6.4.0.34.1 clang-2100.3.34.1).14 Restent deux clôtures, et j’ai essayé les deux.
Une condition de compilation que vous définissez vous-même. C’est la voie documentée. Définissez un drapeau uniquement dans la configuration que vous compilez avec la bêta (dans Xcode, SWIFT_ACTIVE_COMPILATION_CONDITIONS = DUO_SDK ; en ligne de commande, -D DUO_SDK) et clôturez avec lui le code propre à 27.1 :
struct Pair<Primary: View, Secondary: View>: View {
@ViewBuilder var primary: Primary
@ViewBuilder var secondary: Secondary
var body: some View {
#if DUO_SDK
if #available(iOS 27.1, *) {
ArrangementView { primary } secondary: { secondary }
.arrangementViewStyle(.split)
} else {
HStack(spacing: 0) { primary; secondary }
}
#else
HStack(spacing: 0) { primary; secondary }
#endif
}
}
Sans le drapeau, ce fichier passe la vérification de types sous Xcode 27.0 et sous la bêta 27.1. Avec le drapeau, il la passe sous la bêta et échoue sous 27.0 avec la même erreur de symbole introuvable : la mauvaise combinaison ne compile pas.14
La version propre du SDK, lue par le compilateur. canImport accepte un second argument préfixé d’un trait de soulignement, comparé à la version d’un module, et la version du module SwiftUI diffère d’un SDK à l’autre : 8.0.84.1.104 dans le SDK 27.0, 8.0.85.27 dans le SDK 27.1, 8.1.6.1.101 dans le SDK de la bêta 27.2.14 Ceci ne demande donc aucun réglage de build :
#if canImport(SwiftUI, _version: 8.0.85)
// ArrangementView, reservedRegions, onHingeChange, toolbarVerticalBehavior
#else
// what the app did before
#endif
J’ai placé un #warning dans chaque branche et compilé avec les trois Xcode : 27.0 a pris la seconde branche, la bêta 27.1 et la bêta 27.2 ont pris la première.14 La prudence tient au trait de soulignement. La grammaire de cette condition dans le livre Swift est canImport(import-path) et rien de plus ; _version: est donc une fonctionnalité du compilateur sans contrat documenté, et le nombre 8.0.85 est une valeur que j’ai lue dans deux SDK, pas une valeur publiée par Apple.14 Utilisez-la tant que la boutique est fermée à 27.1 si un réglage de build est malcommode dans votre configuration ; prenez le drapeau si vous voulez quelque chose que vous pouvez défendre.
Dans les deux cas, la clôture est temporaire. Le jour où App Store Connect acceptera les builds d’un Xcode qui contient le SDK 27.1, supprimez-la et gardez les vérifications #available, car ce sont elles qui protègent un téléphone encore sous iOS 27.0.
Soumettre : ce qu’App Store Connect accepte aujourd’hui
TestFlight accepte le build 27.1. Les notes de version d’App Store Connect du 18 septembre : « You can now submit apps built with Xcode 27.1 beta using the SDK for iOS 27.1 beta or iPadOS 27.1 beta for internal and external testing. » (Vous pouvez désormais soumettre aux tests internes et externes des apps compilées avec Xcode 27.1 beta et le SDK d’iOS 27.1 beta ou d’iPadOS 27.1 beta.) Les entrées du 16 et du 28 septembre disent la même chose pour Xcode 27.2 beta et beta 2.8 Kiradex passe par là ; son cinquième build, celui que teste ce billet, a été téléversé le 2 octobre, et App Store Connect l’indique comme valide.13
L’App Store, pas encore. L’entrée la plus récente qui ouvre la boutique date du 14 septembre : « You can now upload apps built with Xcode 27 using the SDK for iOS 27.0, iPadOS 27.0, macOS 27.0, tvOS 27.0, visionOS 27.0, and watchOS 27.0 for the App Store, and for internal and external testing through TestFlight. » (Vous pouvez désormais téléverser des apps compilées avec Xcode 27 et les SDK 27.0 pour l’App Store, ainsi que pour les tests internes et externes via TestFlight.)8 Rien après elle ne mentionne 27.1 et la boutique dans la même phrase, et le flux Releases d’Apple, dont les éléments les plus récents datent du 28 septembre, ne liste qu’un build de Xcode 27.1, la bêta du 18 septembre.8 Apple n’a pas dit quand cela changera. L’appareil sera en vente le 23 octobre.1
À moins qu’Apple n’ouvre la boutique au SDK 27.1 avant le 23 octobre, le build que vos clients auront depuis la boutique le jour du lancement sera au mieux un build du SDK 27.0, et la comparaison ci-dessus dit ce qu’il obtient dans le simulateur, la présentation d’Apple décrivant le même niveau intermédiaire : l’écran à côté du bandeau d’état, des barres horizontales, aucune pliure. C’est une app utilisable si elle se redimensionne bien, et c’est l’argument pour publier dès maintenant, avec Xcode 27, le travail de redimensionnement.
Un écran de lancement est désormais obligatoire. Ce n’est pas une règle propre au Duo, mais elle arrive avec le même SDK et elle échoue au téléversement, pas à la revue. La note technique d’Apple : « Starting in iOS 27 and iPadOS 27, App Store Connect requires your app to include a launch screen configuration in its Info.plist, » (À partir d’iOS 27 et d’iPadOS 27, App Store Connect exige que votre app inclue une configuration d’écran de lancement dans son Info.plist), et sans l’une des clés UILaunchStoryboardName, UILaunchStoryboards, UILaunchScreen ou UILaunchScreens, le téléversement est refusé avec « ITMS-90870: Missing launch screen. »10 Kiradex déclare UILaunchScreen avec une couleur, le rouge de sa couverture, si bien que le lancement enchaîne directement sur l’animation d’ouverture.13
Les emplacements de captures existent sur le papier. Les spécifications de captures d’écran d’App Store Connect listent l’iPhone Duo depuis le 9 septembre, en deux paires : 1398 par 2034 ou 2034 par 1398 pixels pour l’écran externe, et 2007 par 2853 ou 2853 par 2007 pour l’écran interne, avec la mention « Support for uploading assets for this device in App Store Connect will be available later this year. » (La prise en charge du téléversement de ressources pour cet appareil dans App Store Connect arrivera plus tard dans l’année.)9 Les règles habituelles s’appliquent : « You can upload one to 10 screenshots in .jpeg, .jpg, and .png formats, » (Vous pouvez téléverser de une à 10 captures aux formats .jpeg, .jpg et .png) et « Images can’t include alpha channels or transparencies. » (Les images ne peuvent pas contenir de couche alpha ni de transparence.)9
Une phrase de la page de téléversement décide de la manière de s’organiser : « Once your app is submitted for review and approved, you must create a new version to update the screenshots. » (Une fois votre app soumise à la revue et approuvée, vous devez créer une nouvelle version pour mettre à jour les captures.)9 Les captures du Duo ne peuvent pas être glissées plus tard toutes seules ; quand les emplacements ouvriront, elles voyageront avec une version.
Mis bout à bout, voici l’enchaînement que je suivrais, et que je suis pour Kiradex :
- Le build 27.1 dans TestFlight dès maintenant, avec les constats du parcours corrigés au fil de l’eau.
- Pour une app déjà sur la boutique : une mise à jour compilée avec Xcode 27 qui embarque toutes les corrections n’exigeant pas le SDK 27.1. Des classes de taille plutôt que des tests d’idiome et d’orientation, des zones sûres par bord, des barres détenues par des conteneurs système, un titre et un symbole sur chaque élément de barre d’outils.
- Des captures aux tailles du Duo, prises dès maintenant dans le simulateur, et conservées.
- Une version tenue prête pour le jour où deux conditions seront réunies : un Xcode doté du SDK 27.1 est accepté pour la boutique, et les emplacements du Duo acceptent les téléversements. Jusqu’ici, Apple a publié chaque changement de ce type dans les notes de version d’App Store Connect, parmi lesquelles l’entrée du 14 septembre qui a ouvert la boutique à la version finale de Xcode 27 et celle du 9 septembre qui a ajouté les spécifications de captures du Duo ; c’est donc la page à surveiller, avec à côté la page des actualités pour les développeurs.8
Une autre exigence se profile plus loin. À partir d’avril 2027, « iOS and iPadOS apps must be built with the iOS 27 & iPadOS 27 SDK or later » (les apps iOS et iPadOS doivent être compilées avec le SDK d’iOS 27 et d’iPadOS 27 ou plus récent) pour pouvoir être téléversées.18 Une app encore compilée avec un SDK iOS 26 obtient sur un Duo la plus petite des trois images ci-dessus, et à partir d’avril 2027 elle ne peut plus téléverser de mise à jour tant qu’elle n’est pas passée au SDK iOS 27.
Des captures pour deux écrans
Le parcours a déjà produit la matière première : chaque arrêt a été capturé en 1398 par 2034 et 2853 par 2007 pixels, et une fois pivoté en 2034 par 1398 et 2007 par 2853, soit les quatre tailles de la ligne iPhone Duo d’App Store Connect.913 Reste à décider ce qui les entoure, et c’est là qu’un téléphone pliable invite à l’erreur.
L’image que tout le monde veut, c’est le téléphone à demi ouvert, de biais, l’app qui se déverse par-dessus la pliure. Les directives marketing d’Apple l’excluent ligne par ligne. Pour les images d’appareils d’Apple elle-même : « Use Apple product images ‘as is’ and without modification. Modifications include adding reflections, shadows, highlights, or graphic elements that appear to enter or come out of the product screen; cropping, tilting, or obstructing any part of the images; animating, flipping, or spinning the images » (Utilisez les images de produits Apple telles quelles, sans modification ; sont des modifications l’ajout de reflets, d’ombres, de brillances ou d’éléments graphiques qui semblent entrer dans l’écran ou en sortir, le recadrage, l’inclinaison ou le masquage d’une partie des images, ainsi que leur animation, leur retournement ou leur rotation). Pour les visuels que vous créez vous-même : « Straight-on product shots are preferred. Don’t use extreme angles or alter an Apple product in any way. » (Les prises de vue de face sont préférées ; n’utilisez pas d’angles extrêmes et ne modifiez en rien un produit Apple.) Et sous « Unauthorized Uses » (utilisations non autorisées), en tête de liste : « Rendering in 3D or creating any simulation of an Apple product » (le rendu en 3D ou toute simulation d’un produit Apple).11 Mon billet sur les captures d’écran examine comment les lauréats traitent ces règles et à quoi ressemble une série qui les respecte ; une charnière n’y change rien.
Ce qu’Apple vous donne à la place, c’est un kit de contours pour ce téléphone, en deux finitions et cinq vues : le téléphone fermé en portrait et en paysage, l’écran interne ouvert en paysage et en portrait, et le téléphone ouvert vu de dos, avec l’écran externe à côté des caméras. Les ouvertures de ces fichiers ont exactement les tailles des captures, si bien qu’une capture du simulateur s’y insère sans mise à l’échelle.11 Il n’y a ni vue à demi pliée ni vue de biais.
Les visuels ci-dessous sont donc construits à partir de trois éléments : un fond aux couleurs de l’app, une courte ligne de texte, et la capture dans le contour d’Apple, entière et droite, sans rien par-dessus. La variété vient du fond, de la taille de l’appareil, et d’un visuel par série qui ne montre aucun appareil : la carte plein écran de l’app sur fond noir, qui est la 3D de l’app elle-même et le matériel de personne.

Trois séries composées par script à partir des captures du parcours, en 1320 par 2868, 1398 par 2034 et 2853 par 2007 pixels. Elles montrent la méthode, pas la fiche : ces captures portent des cartes du catalogue, et ce que montrera la série de la boutique est la question ouverte de la troisième remarque ci-dessous.
Trois remarques pratiques tirées de leur fabrication.
Composer par script. Les séries ci-dessus sortent d’un seul fichier Python qui prend une capture, un titre et un fond, et écrit un PNG à la taille exacte, sans couche alpha. Quand l’app change, et celle-ci a changé deux fois le jour où je l’ai capturée, le parcours se relance et les visuels se reconstruisent.
Capturer ce que le téléphone ajoute. La page de téléversement d’Apple dit qu’une série en 6,9 pouces suffit quand l’interface est la même sur toutes les tailles : « provide only the highest resolution screenshots required. They automatically scale down to smaller device sizes. » (Fournissez uniquement les captures de plus haute résolution requises ; elles sont automatiquement réduites pour les appareils plus petits.)9 Sur ce téléphone, elle n’est pas la même : le mur de cartes et l’inspecteur scindé n’existent que sur l’écran interne. Ce sont les deux visuels qui ouvrent la série interne.
Faire attention à ce qui est à l’écran. Les mêmes directives disent : « You are responsible for securing the rights to all materials used in screen content within your app. » (Il vous incombe d’obtenir les droits sur tous les éléments utilisés dans le contenu affiché par votre app.)11 Une app de collection montre par nature les œuvres d’autres personnes, et une fiche de boutique relève du marketing, ce qui n’est pas la même chose que ce que l’app affiche à l’usage. Nous n’avons pas encore tranché cette question pour Kiradex, et les visuels ci-dessus ne seront pas soumis en l’état. C’est pour cette raison que le parcours a un second mode qui tourne sur six cartes inventées ; elles n’ont pas encore d’illustrations, donc soumettre une série implique de concevoir des substituts ou de régler la question des droits.
Kiradex n’a pas encore de fiche. Quand elle en aura une, elle commencera par une série en 6,9 pouces, et les séries du Duo attendront, avec une version à elles, le jour où App Store Connect les acceptera.
Confier le travail à un agent de code
L’essentiel de ce travail est du genre qu’un agent fait bien, à condition qu’il puisse voir l’app. Deux moitiés, et Apple fournit l’une d’elles.
La moitié statique appartient à Apple. Le premier Tech Talk se termine sur elle : « During the talk, Modernize Your UIKit App, we introduced a new app modernization skill. With Xcode 27.1, this skill has a new name: App Resizability. It now supports SwiftUI and iPhone Duo. » (Lors de la présentation Modernize Your UIKit App, nous avons présenté une nouvelle compétence de modernisation d’app ; avec Xcode 27.1, elle s’appelle désormais App Resizability et prend en charge SwiftUI et l’iPhone Duo.) (9:19)3 Cette compétence est un ensemble de fichiers texte brut à l’intérieur de la bêta : dans Xcode 27.1 beta, Contents/PlugIns/IDEIntelligenceChat.framework/Versions/A/Resources/app-resizability.idechatprompttemplate et cinq fichiers de référence à côté.15 Ses instructions disent jusqu’où ratisser : « Treat a request about the foldable iPhone Duo as a request for every task in the Task Registry, because a screen that changes size exposes all of them at once. » (Traitez une demande portant sur l’iPhone Duo pliable comme une demande portant sur chaque tâche du Task Registry, car un écran qui change de taille les expose toutes à la fois.)15
Elle vaut d’être lue même si vous ne l’exécutez jamais, car c’est la liste de contrôle d’Apple mise par écrit. Elle vérifie trois réglages du projet sans en modifier aucun (une clé d’écran de lancement, la déclaration d’orientations iPad, UIRequiresFullScreen), puis traque cinq motifs : UIScreen.main, une mise en page décidée par l’orientation de l’interface, une mise en page décidée par userInterfaceIdiom, un cycle de vie d’application là où devrait se trouver un cycle de vie de scène, et du code de zone sûre qui suppose que les deux côtés sont identiques. Le fichier sur la zone sûre contient la phrase qui explique la moitié de ce qui tourne mal sur ce téléphone : « Asymmetric horizontal insets are the normal case. Where a vertical bar is present, one horizontal edge usually carries the whole inset and the other carries zero. » (Des marges horizontales asymétriques sont le cas normal ; en présence d’une barre verticale, un bord porte généralement toute la marge et l’autre zéro.)15
Kiradex est une app SwiftUI écrite cette année, et ces cinq recherches n’y trouvent rien.13 Chaque constat ci-dessus est venu de son exécution. C’est la limite de la moitié statique : elle lit le source, et la pliure, le bandeau et le clavier ne sont visibles que sur un écran.
L’autre moitié est un parcours que l’agent peut lancer et regarder. Ce qui a rendu possible l’audit ci-dessus, ce sont trois petites pièces, dont aucune n’est propre à cette app :
- Un test d’interface qui visite chaque type d’écran et s’arrête sur chacun. Pas d’assertions ; une visite guidée. La nôtre ouvre le Dex, une série, une carte, une feuille, la liste de la collection, une carte de la collection, la visionneuse plein écran et la recherche avec le clavier affiché : huit arrêts.13
- Une capture qui se fait sur le Mac, pas dans le test. La capture d’un test d’interface ne couvre qu’un écran.
simctlatteint les deux :
xcrun simctl io "$UDID" screenshot --type=png --display=primary outer.png
xcrun simctl io "$UDID" screenshot --type=png --display=primary-1 inner.png
Le test écrit un fichier vide nommé d’après l’arrêt ; une boucle shell sur le Mac le voit, capture les deux écrans et répond par un second fichier ; le test l’attend puis poursuit. La capture externe mesure 1398 par 2034 pixels téléphone fermé et l’interne 2853 par 2007 téléphone ouvert, si bien que les images de l’audit et les captures pour la boutique sortent de la même exécution.913
3. Un moyen de changer de position sans toucher la souris. simctl n’a pas de commande de position et les frameworks de test d’interface de cette bêta n’ont aucun appel lié à la charnière que j’aie pu trouver ; le script appuie donc sur les boutons Closed, Book, Open et Rotate Right de Device Hub via l’API d’accessibilité, ce qui fonctionne même quand Device Hub est en arrière-plan.13
Avec cela, vérifier l’app dans chaque position cesse d’être une demande d’avis adressée à l’agent et devient un dossier d’images par position, que lui comme vous pouvez lire. Le brief ci-dessous est celui que je confierais. Il est écrit pour être collé tel quel.
Goal: make this app correct on iPhone Duo in every pose, without device checks.
0. Toolchain. Build with Xcode 27.1 beta. Confirm the binary is stamped with the 27.1 SDK:
otool -l <App>.app/<App> | grep -A4 LC_BUILD_VERSION (debug builds: <App>.debug.dylib)
If "sdk" is lower than 27.1, stop: nothing below will reproduce.
1. Static pass. Report every use, with file and line, of:
UIScreen.main / UIScreen.mainScreen; userInterfaceIdiom; interface orientation used for layout;
a UIApplicationDelegate doing scene work; one safe-area inset applied to both sides;
a bare ignoresSafeArea() on anything a person reads or taps; fixed widths tied to a phone size;
toolbars or tab bars built by hand instead of owned by NavigationStack, NavigationSplitView or TabView;
toolbar items with a title and no symbol, or a symbol and no title.
Confirm Info.plist has a launch screen key and no orientation lock the design does not need.
2. Walk. Run the screenshot tour in each pose and capture BOTH displays at every stop:
closed; closed and turned; open; open and turned; partly folded; partly folded and turned.
If no tour exists, write a UI test that stops at each kind of screen and signals a host script, and have
the script capture with: xcrun simctl io <udid> screenshot --display=primary (outer)
xcrun simctl io <udid> screenshot --display=primary-1 (inner)
Poses are buttons in Device Hub (Closed, Book, Open, Rotate Right); simctl has no pose command.
3. Read every capture and answer, per pose:
- Are the bars where the system puts them (down the side closed and in open landscape, across the top
and bottom in open portrait)? Is any toolbar item missing from the bar and from the overflow menu?
- Does any sheet reserve the side rail and leave it empty?
- With the keyboard up, what is covered? Can every tab still be reached once it is dismissed?
- Does anything sit under the outer camera corner or the status column?
- Open: does a grid have an even number of columns? Does any control or line of text cross the middle?
- Partly folded: does content move off the fold? Do sheets and alerts land on one side?
- Turned: did a two-pane layout stack when it should have stayed side by side, or the reverse?
- Is the same selection, scroll position and navigation path still there after the pose changed?
4. Fix with, in this order: a system container that already adapts; size classes; ArrangementView for a
custom two-pane layout; reservedRegions for hand-placed content. Never branch on the device model,
the idiom, the orientation, or the raw hinge angle to decide layout.
5. Guard everything from the 27.1 SDK with `if #available(iOS 27.1, *)` and a fallback that keeps both
panes reachable. If the same source must also build with Xcode 27.0, fence it at compile time.
6. Report what could not be checked in the simulator: cameras, StandBy, extensions, haptics, real reach.
La documentation d’Apple, dans l’ordre où je l’utiliserais
Tout ce qu’Apple a publié pour cet appareil se rattache à une seule page, Get ready for iPhone Duo.19 Dans l’ordre de travail :
| Quoi | Pourquoi l’ouvrir |
|---|---|
| Prepare your app for iPhone Duo (Tech Talk) | Les trois niveaux de SDK, les classes de taille, les zones sûres. Commencez ici |
| Preparing your app for iPhone Duo (guide) | Le même terrain sous forme de texte, avec chaque API nommée. Les quatre vérifications de « Address common layout and resizing considerations » forment la liste d’audit2 |
| Raise the bar with iPhone Duo | Les barres verticales : ce qui y entre, ce qui reste dehors, le débordement |
| Strike a pose with adaptive layouts on iPhone Duo | La pliure : déplacement, régions réservées, vues d’arrangement |
| Designing for iPhone Duo (HIG) et Design for iPhone Duo | Les règles qu’un designer vous opposera7 |
| Leverage multiple displays and scenes on iPhone Duo | La charnière, Split View, une seconde scène sur l’écran externe |
| Build a great camera experience for iPhone Duo | Seulement si vous capturez : deux caméras frontales et l’orientation de chacune6 |
| Enregistrements des Group Labs, jour 1 et jour 2, et les questions-réponses du forum pour SwiftUI, UIKit et Photos and Camera | Des ingénieurs d’Apple répondent aux questions des développeurs19 |
| Apple Design Resources | Kits Figma et Sketch, et les contours de produits pour le marketing11 |
| Hors d’Apple : le guide du simulateur de SwiftLee, iPhone Duo by Examples, la liste de contrôle de BleepingSwift, le guide d’Adapty | Une liste de tests et le curseur de charnière ; un exemple exécutable par API, avec des notes de terrain ; une courte liste de contrôle ; le seul que j’aie trouvé qui traite d’un paywall de bout en bout17 |
| Ateliers | En personne. SwiftLee précise qu’ils viennent « with the opportunity to test your app on a physical device, » (avec la possibilité de tester votre app sur un appareil physique), ce qui, avant le 23 octobre, est le seul moyen de vérifier une caméra1719 |
Je n’ai lu ni la synthèse des questions-réponses des Group Labs ni les fils du forum : les pages du forum d’Apple répondent à une récupération automatisée par une page de vérification humaine, et je ne l’ai pas contournée.
Points clés à retenir
- Si vous publiez une app aujourd’hui : publiez dès maintenant le travail de redimensionnement, compilé avec Xcode 27. C’est ce que vos clients auront sur un Duo le 23 octobre si la boutique est encore fermée au SDK 27.1 ce jour-là, et rien de tout cela n’a besoin de la bêta.
- Si vous adoptez les API du Duo : compilez avec Xcode 27.1 beta, confirmez
sdk 27.1ou plus avecotool, gardez le build dans TestFlight, et clôturez les appels propres à 27.1 si le même source doit encore compiler pour la boutique. - Si vous testez : ne lisez pas le code, parcourez les positions. Fermé, ouvert, partiellement plié, chacune pivotée, une feuille, le clavier, une vue plein écran, et un écran resté ouvert pendant le dépliage. Capturez les deux écrans à chaque fois.
- Si vous préparez la fiche de la boutique : capturez dès maintenant aux tailles du Duo, composez par script, utilisez les contours d’Apple de face, et gardez une version prête pour le jour où les emplacements ouvriront.
- Si vous confiez cela à un agent : donnez-lui le parcours, pas seulement les fichiers. La compétence App Resizability d’Apple couvre ce qui se trouve en lisant ; tout ce qui figure dans les constats ci-dessus a été trouvé en regardant.
Questions fréquentes
Mon app actuelle fonctionne-t-elle sur l’iPhone Duo sans modification ?
Oui. La présentation d’Apple le promet pour n’importe quel SDK, et le simulateur le confirme : un build tamponné avec le SDK iOS 26 a tourné dans une fenêtre de 375 par 667 points, et un build tamponné 27.0 a rempli l’écran à côté du bandeau d’état avec des barres horizontales. Aucun des deux n’obtient de barres verticales ni de régions réservées.312
Quel Xcode faut-il pour la mise en page complète de l’iPhone Duo ?
Xcode 27.1 beta (27A9269), qui contient le SDK iOS 27.1 et le seul simulateur de l’iPhone Duo. Son runtime de simulateur 27.1 ne prend en charge que le type d’appareil iPhone Duo, si bien que les autres iPhone se testent sur le runtime 27.0. Le SDK de la bêta de Xcode 27.2 contient les mêmes API, et une app sonde tamponnée 27.2 s’est comportée comme 27.1 dans le simulateur, mais ce Xcode n’a aucun Duo sur lequel tourner.81214
Puis-je soumettre aujourd’hui un build pour l’iPhone Duo à l’App Store ?
Pas un build compilé avec le SDK 27.1, au 2 octobre 2026. App Store Connect accepte les builds des bêtas de Xcode 27.1 et 27.2 pour les tests TestFlight internes et externes, et les builds de Xcode 27 pour la boutique. Apple n’a pas daté le changement.8
Quelles tailles de captures App Store Connect demande-t-il pour l’iPhone Duo ?
1398 par 2034 ou 2034 par 1398 pixels pour l’écran externe, et 2007 par 2853 ou 2853 par 2007 pour l’écran interne, de une à dix images sans couche alpha. Leur téléversement est annoncé pour « later this year » (plus tard dans l’année).9
Comment capturer les deux écrans du simulateur de l’iPhone Duo ?
xcrun simctl io <udid> screenshot --display=primary pour l’écran externe et --display=primary-1 pour l’écran interne. La capture propre d’un test d’interface ne couvre qu’un écran.13
Pourquoi les barres de mon app sont-elles encore horizontales dans le simulateur de l’iPhone Duo ?
Trois causes, dans l’ordre où les vérifier. Le binaire n’est pas tamponné avec le SDK 27.1. Les barres sont faites main au lieu d’appartenir à un TabView, un NavigationStack ou un NavigationSplitView. Ou l’écran interne est en portrait, où Apple garde les barres horizontales par conception.2712
Faut-il une mise en page pour chaque position ?
Non. Les recommandations d’Apple prévoient deux mises en page, largeur compact et largeur regular, plus une réaction à la pliure là où du contenu la traverserait. Kiradex a ces deux-là et une vue d’arrangement ; la position Book n’a demandé aucun code.713
À lire aussi sur ce site : le billet sur le simulateur donne les étapes d’installation, le profil de l’appareil et les mesures corrigées par position ; concevoir pour l’iPhone Duo lit les recommandations de conception d’Apple comme des règles ; le billet Duo pour les développeurs donne les chiffres du matériel et l’historique daté ; le billet sur les captures d’écran défend ce qu’une série doit dire ; la liste de contrôle de l’iPhone redimensionnable est le travail Xcode 27 que ce billet vous conseille de publier en premier ; et le hub Xcode 27 suit la chaîne d’outils.
Sources
-
Apple Newsroom, Apple unveils iPhone Duo, 9 septembre 2026, consulté le 2 octobre 2026 : « Pre-orders begin Friday, October 16, with availability beginning Friday, October 23. » (Précommandes à partir du vendredi 16 octobre, disponibilité à partir du vendredi 23 octobre.) et « iPhone Duo will be available with iOS 27.1. » (L’iPhone Duo sera disponible avec iOS 27.1.) ↩↩↩
-
Apple, Preparing your app for iPhone Duo, Technology Overviews, consulté via le point de terminaison JSON de la documentation le 2 octobre 2026 ; sont cités la vue d’ensemble et les sections « Address common layout and resizing considerations », « Organize items in your bars » et « Arrange views in different poses ». La phrase de la vue d’ensemble sur les versions de Xcode était formulée autrement quand ce site l’a citée le 17 septembre 2026 (« Build your app with Xcode 27.1 or later to use all of the available screen space on iPhone Duo. In earlier versions, your app doesn’t extend under the status bar and camera. ») ; le billet Duo pour les développeurs de ce site a consigné la formulation actuelle le 19 septembre. La page ne porte aucune mention de révision. ↩↩↩↩↩↩
-
Apple Developer Tech Talk, Prepare your app for iPhone Duo, David Jackson, UI Frameworks. Citations tirées de la piste de sous-titres anglais de la présentation, aux instants indiqués. ↩↩↩↩
-
Apple Developer Tech Talk, Raise the bar with iPhone Duo, Anna, ingénieure UI Frameworks, et Maria, Human Interface Designer. Citations tirées de la piste de sous-titres anglais de la présentation, aux instants indiqués. ↩↩↩
-
Apple Developer Tech Talk, Strike a pose with adaptive layouts on iPhone Duo, Maria, Human Interface Designer, et Harry, ingénieur UI Frameworks. Citations tirées de la piste de sous-titres anglais de la présentation, aux instants indiqués. ↩↩↩
-
Apple Developer Tech Talks, Leverage multiple displays and scenes on iPhone Duo et Build a great camera experience for iPhone Duo, citations tirées des pistes de sous-titres anglais aux instants indiqués ; Apple, Choosing a camera by the direction it faces, AVKit, consulté le 2 octobre 2026. ↩↩↩
-
Apple, Designing for iPhone Duo, Human Interface Guidelines, consulté via le point de terminaison JSON de la documentation le 2 octobre 2026 ; sont citées les sections « Device poses » et « Vertical controls ». ↩↩↩↩↩
-
Apple, App Store Connect release notes, consulté le 2 octobre 2026 : sont citées les entrées datées du 14 et du 18 septembre 2026 ; l’entrée datée du 9 septembre ajoute les spécifications de captures pour l’iPhone Duo et indique que leur téléversement « will be available later this year », la phrase que reprend la page des spécifications ; les entrées datées du 16 et du 28 septembre ouvrent TestFlight à Xcode 27.2 beta et beta 2 sous la même forme, pour six plateformes ; aucune entrée postérieure au 18 septembre ne mentionne Xcode 27.1 ni le SDK iOS 27.1. Apple, Releases, flux RSS consulté le 2 octobre 2026, dernière date de génération Mon, 28 Sep 2026 14:00:00 PDT : un seul élément mentionne Xcode 27.1, « Xcode 27.1 beta (27A9269) » daté du Fri, 18 Sep 2026 ; l’élément Xcode le plus récent est « Xcode 27.2 beta 2 (27B5028f) » daté du Mon, 28 Sep 2026. ↩↩↩↩↩↩↩↩↩↩↩
-
Apple, Screenshot specifications et Upload app previews and screenshots, aide d’App Store Connect, consultés le 2 octobre 2026, cités. ↩↩↩↩↩↩↩↩↩↩
-
Apple, TN3208: Preparing your app’s launch screen to meet App Store requirements, consulté le 2 octobre 2026, cité ; historique des révisions : « 2026-09-14 Updated the ITMS-90870 error message to reflect the iOS 27 launch screen requirement. » et « 2026-06-08 First published. » ↩↩↩
-
Apple, Marketing Resources and Identity Guidelines, sections « Apple Product Images », « Unauthorized Uses », « Screen Content » et « Custom Photography and Video », consulté le 2 octobre 2026, cité. Apple, Apple Design Resources, Product Bezels, iPhone Duo (Photoshop et PNG), consulté le 2 octobre 2026. Les mesures des contours sont de l’auteur, à partir des fichiers PNG du
Bezel-iPhone-Duo.dmgd’Apple : « Outer Closed Portrait » mesure 1574 par 2194 pixels avec une ouverture transparente de 1398 par 2034 ; « Inner Open Landscape » mesure 3093 par 2247 avec une ouverture de 2853 par 2007 ; le kit contient aussi « Inner Open Portrait », « Outer Closed Landscape » et « Outer Open », chacun en Star White et Night Sky. La découpe de la caméra dans « Outer Closed Portrait », mesurée à l’intérieur de l’ouverture à trois pixels par point, s’étend de 400,3 à 436,3 points en largeur et de 29,7 à 65,7 en hauteur ; l’occultation de caméra de l’app sonde s’étend de 399 à 436 et de 30 à 67. ↩↩↩↩↩↩ -
Exécutions de l’auteur le 2 octobre 2026 : macOS 27.0 (26A428), Xcode 27.1 beta (27A9269), le runtime de simulateur iOS 27.1 (24A94401) et un simulateur créé à partir du type d’appareil iPhone Duo. L’app sonde, DuoProbe2, est un seul fichier Swift : un
TabViewdont le premier onglet contient unNavigationStackavec cinq éléments de barre d’outils, un affichage de la taille duGeometryProxy, des classes de taille, detoolbarVerticalEdge, deonHingeChangeet desreservedRegionsdes deux types avec.includeInactive, lu à chaque évaluation du body et réévalué une fois par seconde, uneArrangementViewde style split, et une vue UIKit qui journalise sa fenêtre, l’écran de la scène de sa fenêtre,UIScreen.mainet le traitverticalBarEdge. Elle a été compilée trois fois à partir de ce fichier avecswiftccontre le SDK de simulateur 27.1, cible de déploiement 27.1, en indiquant à l’éditeur de liens quelle version de SDK consigner (-Xlinker -platform_version -Xlinker ios-simulator -Xlinker 27.1 -Xlinker <26.0, 27.0 or 27.1>) ;otool -lsur chaque binaire a affiché la valeursdkcorrespondante. Les positions ont été réglées avec les boutons Closed, Book, Open et Rotate Right de Device Hub, actionnés via l’API d’accessibilité. Lignes de console, tampon 27.1, fermé :size=382x562 ... h=compact v=regular verticalEdge=trailing safe=EdgeInsets(top: 82.0, leading: 0.0, bottom: 34.0, trailing: 84.0) divisions=0 occlusions=2,occlusion[0] active=true frame=(399,-52 37x37),occlusion[1] active=true frame=(382,-82 84x170),window=(466.0, 678.0),verticalBarEdge=2; ouvert :size=867x553 ... h=regular v=regular verticalEdge=trailing ... divisions=1 occlusions=2,division[0] active=false frame=(455,-82 40x669) margins=EdgeInsets(top: 0.0, leading: 20.0, bottom: 0.0, trailing: 20.0),occlusion[0] active=false frame=(677,-61 58x37),occlusion[1] active=true frame=(867,-82 84x120),window=(951.0, 669.0),hinge=fullyOpen 180 deg; Book : les mêmes avecdivision[0] active=trueethinge=partiallyOpen 127 deg; ouvert et pivoté :size=669x734 ... verticalEdge=nil ... divisions=1 occlusions=2,division[0] active=false frame=(0,321 669x40),window=(669.0, 951.0),mainScreen=(466.0, 678.0),verticalBarEdge=0; fermé et pivoté :size=594x350 ... h=compact v=compact verticalEdge=trailing,window=(678.0, 466.0). Les cadres sont exprimés dans les coordonnées de la vue d’affichage, dont l’origine se situe 82 ou 134 points sous le haut de la fenêtre. Tampon 27.0 :window=(386.0, 678.0)fermé,(871.0, 669.0)ouvert,(669.0, 871.0)ouvert et pivoté,(678.0, 386.0)fermé et pivoté, avecverticalEdge=niletdivisions=0 occlusions=0sur chaque ligne dans chaque position. Tampon 26.0 :window=(375.0, 667.0)fermé, ouvert, en Book et ouvert et pivoté, et(667.0, 375.0)fermé et pivoté, avech=compactpartout. À chaque lancement en 27.1, les six à neuf premières évaluations ont journalisédivisions=0 occlusions=0avant l’apparition des régions, dont trois avant que la vue ait une taille. Les positions des volets en Open et en Book ont été mesurées sur les captures : à plat, volet principal de x 8 à 433,7 et volet secondaire de 433,7 à 859 ; en Book, volet principal jusqu’à 455,7, une bande vide jusqu’à 495,7, volet secondaire jusqu’à 859. Feuilles, fermé : contenu374x562avec un Done textuel, idem avec un symbole sur Done,450x428etverticalEdge=nilavec.toolbarVerticalBehavior(.disabled); ouvert :653x501centré avech=compact; Book :459x501au bord de tête. Avec la vue d’arrangement remplissant la zone de contenu (une option de lancement), un.splitsimple a placé le volet principal au-dessus du secondaire sur l’écran pivoté et.split.axes(.horizontal)a montré le volet principal seul ; ouvert et à plat, la même vue a partagé côte à côte, et en Book elle a laissé vide la bande de la pliure. Une app sonde compilée comme le décrit le billet du 21 septembre (swiftc -sdkavecSDKROOTnon défini) a affichéclang: warning: using sysroot for 'macOS 27.0' but targeting 'arm64-apple-ios27.1.0-simulator'et a été tamponnéesdk 27.0. Deux builds supplémentaires ont tourné fermé et ouvert. PlainProbe, avec le même tab view, la même pile de navigation et la même barre d’outils et rien qui vienne du SDK 27.1, compilée par Xcode 27.0 (27A266a) contre son propre SDK iOS 27.0 (otool:minos 27.0,sdk 27.0) :window=(386.0, 678.0)fermé et(871.0, 669.0)ouvert. DuoProbe2 tamponnéesdk 27.2: les mêmes lignes qu’avec le tampon 27.1 dans les deux positions.simctl list runtimes -jdonne pour le runtime 27.1 une seule entrée danssupportedDeviceTypes, iPhone Duo, etsimctl createavec le type iPhone 18 Pro Max sur ce runtime échoue avec « Incompatible device ». ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩ -
Kiradex est l’app de l’auteur (941 Apps), version 1.0, build 5, téléversée sur TestFlight le 2 octobre 2026 et indiquée comme valide par App Store Connect le même jour. Les éléments du projet proviennent de son code source à ce build : cible de déploiement iOS 27.0, compilée avec le SDK 27.1 (
otool -lsur le binaire de l’app :minos 27.0,sdk 27.1),UILaunchScreenavec une couleur, portrait et les deux paysages, unTabViewà cinq onglets, et deux emplacements#available(iOS 27.1, *), l’un autour d’ArrangementViewet l’autre autour d’onHingeChange. La ligne de la feuille de route est citée d’après les notes du projet. Le parcours est un test d’interface qui s’arrête sur huit types d’écran et demande à un script hôte de capturer le simulateur avecsimctl io <udid> screenshot --display=primaryet--display=primary-1; il a tourné dans six positions sur le simulateur de l’iPhone Duo (runtime iOS 27.1), avec les huit arrêts dans cinq d’entre elles et sept fermé et pivoté, ainsi que sur un simulateur d’iPhone 18 Pro Max (runtime iOS 27.0, portrait et paysage). Tailles de capture : 1398 par 2034 et 2034 par 1398 (externe), 2853 par 2007 et 2007 par 2853 (interne), 1320 par 2868 (6,9 pouces). Le bord gauche de l’inspecteur a été mesuré sur les captures de l’écran interne à x 433,7 à plat et à 495,7 en position Book. Le test de dépliage a lancé l’app fermée, capturé l’écran interne en continu et appuyé sur Open ; quatre images consécutives montrent l’ouverture. Le test de la carte restée ouverte a ouvert une carte en position fermée, appuyé sur Open et capturé vingt secondes plus tard. Le test de la visionneuse a ouvert la visionneuse plein écran quatre fois dans une même session sur le simulateur de 6,9 pouces et mesuré chaque capture : la première comptait 52 % de pixels non noirs, les trois autres 0,3 %. Une recherche textuelle dans les frameworksXCTestetXCUIAutomationde la plateforme simulateur de la bêta de Xcode 27.1 pour « hinge », « posture », « DevicePose » et « foldState » n’a rien trouvé, etsimctlne liste aucune commande de position. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩ -
Test de l’auteur le 2 octobre 2026. Un fichier utilisant
ArrangementViewderrièreif #available(iOS 27.1, *)a été vérifié avecswiftc -typecheckcontre le SDK de simulateur de chaque Xcode installé : Xcode 27.0 (27A266a) a échoué avecerror: cannot find 'ArrangementView' in scope; Xcode 27.1 beta (27A9269) et Xcode 27.2 beta (27B5019j) ont réussi. Le même fichier clôturé par#if DUO_SDKa réussi sous 27.0 sans le drapeau et sous la bêta 27.1 avec et sans, et a échoué sous 27.0 avec-D DUO_SDK. Clôturé par#if canImport(SwiftUI, _version: 8.0.85), il a réussi sous les trois, et un#warningdans chaque branche a montré que 27.0 compilait la solution de repli et les deux bêtas la branche 27.1.xcrun swift --versionafficheApple Swift version 6.4 (swiftlang-6.4.0.34.1 clang-2100.3.34.1)sous les trois. Les versions du module SwiftUI sont les valeurs-user-module-versionduSwiftUI.swiftinterfacede chaque SDK. La bêta 27.2 installée ici est la bêta 1 (27B5019j) ; son runtime de simulateur iOS 27.2 (24B5084k) ne liste pas le type d’appareil iPhone Duo, et les notes 27.2 d’Apple renvoient les développeurs vers la bêta 27.1 pour celui-ci. La grammaire de la condition provient de The Swift Programming Language, Statements, « Conditional Compilation Block », consulté le 2 octobre 2026 : « platform-condition →canImport(import-path)». ↩↩↩↩↩↩↩↩↩ -
Xcode 27.1 beta (27A9269),
Contents/PlugIns/IDEIntelligenceChat.framework/Versions/A/Resources/:app-resizability.idechatprompttemplateetapp-resizability-ref-uiscreen-task.md.packaged,-orientation-task,-scene-lifecycle-task,-safe-area-tasket-idiom-task, lus le 2 octobre 2026 ; les citations proviennent de la section « When to Use » du modèle et de la règle 6 de la référence sur la zone sûre ; les trois vérifications du projet correspondent à son tableau « Prerequisites » et les cinq motifs à son « Task Registry ». Xcode 27.0 (27A266a) contientuikit-app-modernization.idechatprompttemplateet quatre fichiers de référence dans le même dossier. ↩↩↩ -
Apple, documentation consultée via le point de terminaison JSON le 2 octobre 2026 : ArrangementView, reservedRegions(kind:options:layoutDirectionBehavior:), onHingeChange(isEnabled:_:), toolbarVerticalBehavior(_:) et toolbarVerticalEdge. ↩
-
Antoine van der Lee, iPhone Duo Simulator: Testing and optimizing your SwiftUI app, SwiftLee, 22 septembre 2026, cité. Artem Novichkov, iPhone Duo by Examples, README GitHub, « Good to Know », consulté le 2 octobre 2026 : « Its frame is the same in both states: 40 pt wide, with 20 pt margins on each side of a zero-width fold line. », « Reserved regions arrive after the first layout pass. » et « When folded, the outer display has no reserved regions at all, not even inactive ones. » Les deux premiers concordent avec l’app sonde ; le troisième non, puisque l’app sonde a lu deux occultations actives sur l’écran externe fermé. Mick MacCallum, How to Get Your App Ready for iPhone Duo, BleepingSwift, 18 septembre 2026. Yurii Kleimenov, How to adapt your iOS app to iPhone Duo, Adapty, publié le 11 septembre 2026 et marqué comme mis à jour le 15 septembre. ↩↩↩↩↩
-
Apple, « App Store submissions now open for the latest OS releases », actualités pour les développeurs, 9 septembre 2026 : à partir d’avril 2027, les apps téléversées sur App Store Connect « need to meet the following minimum requirements » (doivent satisfaire aux exigences minimales suivantes), dont la première est « iOS and iPadOS apps must be built with the iOS 27 & iPadOS 27 SDK or later ». ↩
-
Apple, Get ready for iPhone Duo, consulté le 2 octobre 2026 : six Tech Talks, deux enregistrements de Group Labs, un lien vers les questions-réponses des Group Labs, des questions-réponses de forum pour Photos and Camera, SwiftUI et UIKit, Xcode 27.1 beta, les recommandations et ressources de conception, le guide de préparation et des ateliers en personne. La page de questions-réponses des Group Labs et les fils du forum n’ont pas été lus ; les requêtes vers eux ont renvoyé une page de vérification humaine. ↩↩↩
-
Apple, Xcode 27.1 Beta Release Notes, consulté via le point de terminaison JSON de la documentation le 2 octobre 2026, Simulator, Known Issues : « StandBy is unavailable in the iPhone Duo Simulator runtime. (187708663) » et « Running and debugging most app extensions is unavailable in the iPhone Duo Simulator runtime. (187708767) ». Apple, Xcode 27.2 Beta 2 Release Notes, consulté de la même façon le 2 octobre 2026 : Overview, « Download Xcode 27.1 beta to get the iOS SDK and simulator support for iPhone Duo. » ; General, Known Issues, 187146039, cité. ↩