
-
Rendez votre app UIKit plus flexible
Découvrez comment vos UIKit app peuvent bénéficier d'une flexibilité accrue sur iPhone, iPad, Mac et Apple Vision Pro à l'aide des contrôleurs de vue Scènes et Conteneurs. Apprenez à libérer tout le potentiel de votre application en passant d'un cycle de vie centré sur l'app à un cycle de vie basé sur des scènes, y compris un redimensionnement amélioré des fenêtres et un mode multitâche amélioré. Explorez les améliorations apportées à UISplitViewController, telles que le redimensionnement interactif des colonnes et la prise en charge de premier ordre des colonnes d'inspecteur. Et améliorez l'adaptabilité de vos vues et commandes en adoptant de nouvelles API de mise en page.
Chapitres
- 0:00 - Introduction
- 0:58 - Scènes
- 4:58 - Contrôleurs de vue de conteneur
- 10:45 - Adaptabilité
- 15:39 - Compatibilité future
- 16:07 - Étapes suivantes
Ressources
Vidéos connexes
WWDC25
WWDC24
-
Rechercher dans cette vidéo…
Bonjour, bienvenue dans « Rendez votre app UIKit plus flexible ». Je m’appelle Alexander MacLeod et je suis ingénieur dans l’équipe UIKit. Une app flexible offre une expérience exceptionnelle, quelle que soit la taille et la plate-forme. Elle préserve une expérience de navigation familière et intuitive quelle que soit la taille. Dans cette vidéo, je vous présente quelques-unes des meilleures pratiques garantissant la flexibilité de votre app. Tout d’abord, j’examinerai les principes fondamentaux des scènes et expliquerai en quoi elles garantissent une app flexible. Ensuite, j’aborderai les contrôleurs de vue de conteneur, comme UISplitViewController et UITabBarController, et étudierai la manière dont ils apportent de la flexibilité à votre app. Enfin, je parlerai des API qui vous aideront à créer une interface adaptative et vraiment flexible. Je commencerai par les scènes. Une scène est une instance de l’interface de votre app. Elle contient les contrôleurs de vue et les vues de votre app. Les scènes fournissent des points d’ancrage pour gérer des données externes, comme une URL établissant un lien étroit avec une section de l’interface de votre app.
Chaque scène enregistre et restaure indépendamment l’état de l’interface. Une scène détermine les meilleurs moments pour interroger l’état actuel, avant de le conserver sur le disque. Vous pouvez interroger l’état précédent de l’interface lors de la reconnexion d’une scène. Cela vous permet de restaurer l’état antérieur exact de la scène. Les scènes fournissent également un contexte sur l’affichage de votre app, notamment des détails sur l’écran et la géométrie de la fenêtre. Vous pouvez avoir plusieurs scènes, chacune ayant son propre cycle de vie et son propre état. Des types de scènes dédiés sont conçus pour encapsuler des expériences distinctes. Par exemple, une app de messagerie peut avoir une scène de composition dédiée à l’envoi de nouveaux messages. Dans iOS 26, vous pouvez désormais mélanger les types de scènes SwiftUI et UIKit dans une même app. Consultez « What’s news in UIKit » pour en savoir plus. La portabilité des scènes constitue la base parfaite d’une app flexible.
Les scènes étant essentielles pour assurer la flexibilité, l’adoption du cycle de vie UIScene sera bientôt obligatoire. Dans la prochaine version majeure faisant suite à iOS 26, le cycle de vie UIScene sera exigé lors de la création avec le dernier SDK.
Bien que la prise en charge de plusieurs scènes soit encouragée, seule l’adoption du cycle de vie basé sur la scène est requise. Pour plus de détails sur l’adoption du cycle de vie d’UIScene, lisez la note technique : « Migrating to the UIKit scene-based life cycle ». Les scènes étant très importantes, je vais vous présenter un cas concret. J’ai développé une app qui suit le temps que je consacre à une tâche particulière. Elle dispose d’une fonction permettant de diffuser la tâche en cours via AirPlay, sur une Apple TV. C’est au délégué d’app de déterminer la configuration de scène pour une séance de connexion. Dans la méthode de délégué configurationForConnecingSceneSession, je vérifie le rôle de séance de la scène. Si le rôle est un affichage externe non interactif, je renvoie une configuration de scène sur mesure. Dans le cas contraire, la configuration de scène principale est privilégiée. Chaque configuration est définie dans le fichier Info.plist de l’app.
UISceneDelegate gère le cycle de vie d’une scène individuelle. Dans sceneWillConnectToSession, je crée d’abord une fenêtre et je l’associe à la scène de connexion. Notez que si votre configuration de scène spécifie un storyboard, la création de fenêtres se fait automatiquement.
Je spécifie le contrôleur de vue racine de la fenêtre et lui fournis des données spécifiques à la scène, comme le modèle de minuterie. Pour mon app, il est important de mettre en pause la minuterie lorsque la scène passe en arrière-plan. Pour ce faire, j’implémente la méthode de délégué sceneDidEnterBackground et je mets en pause la minuterie. Je gère la restauration d’état pour m’assurer que l’état d’interface d’une scène de connexion est exactement tel qu’il a été laissé auparavant. Mon délégué de scène fournit une activité de restauration d’état, qui peut inclure des sélections, des chemins de navigation et d’autres états d’interface. Le système conserve cet état d’interface, en l’associant à l’instance de scène. Si la scène se reconnecte ultérieurement, l’activité de restauration d’état est rendue disponible dans la méthode de délégué userActivity de restoreInteractionStateWith. En renseignant le modèle de minuterie avec des infos sur l’activité de l’utilisateur, je m’assure que l’état d’interface de la scène de connexion est exactement tel qu’il a été laissé auparavant.
En adoptant le cycle de vie UIScene, je dispose de bases solides pour une app flexible. Passons maintenant aux contrôleurs de vue de conteneur et expliquons en quoi ils sont essentiels pour créer une app flexible. Un contrôleur de vue de conteneur est responsable de la gestion de la mise en forme d’un ou de plusieurs contrôleurs de vue enfant. UIKit fournit un certain nombre de contrôleurs de vue de conteneur conçus pour être flexibles. Commençons par UISplitViewController. UISplitViewController gère l’affichage de plusieurs colonnes de contenu adjacentes, ce qui offre une navigation fluide dans une hiérarchie d’informations. Lorsque l’espace horizontal est limité, le contrôleur de vue scindée s’adapte en rassemblant ses colonnes en une pile de navigation. UISplitViewController offre quantité de nouvelles fonctionnalités, dont le redimensionnement interactif des colonnes. Vous pouvez désormais redimensionner les colonnes en faisant glisser les séparateurs du contrôleur de vue scindée. Lorsque vous utilisez le pointeur, sa forme s’adapte pour indiquer les directions dans lesquelles une colonne peut être redimensionnée. UISplitViewController fournit une largeur minimale, maximale et préférée par défaut pour chaque colonne. Certaines colonnes de votre app peuvent préférer afficher du contenu sur des largeurs plus grandes, ou nécessiter une fraction de la largeur par défaut pour rester fonctionnelles. Vous pouvez personnaliser les largeurs minimale, maximale et préférée de chaque colonne à l’aide des propriétés associées du contrôleur de vue scindée. Veillez à ne pas exiger une largeur qui limite le nombre de colonnes pouvant être affichées, car cela réduit la flexibilité de votre app. Votre interface devra peut-être s’adapter selon que le contrôleur de vue scindée est développé ou réduit. Dans Mail, des indicateurs d’affichage s’affichent lorsque le contrôleur de vue scindée est réduit, afin d’indiquer qu’un contenu supplémentaire peut être révélé lors de la sélection d’une cellule. Une nouvelle caractéristique, l’environnement de mise en forme du contrôleur de vue scindée, indique si un contrôleur de vue scindée antérieur est développé ou réduit. Dans cet exemple, la caractéristique est interrogée pour ajouter sous conditions un indicateur d’affichage lorsque le contrôleur de vue scindée est réduit. Autre nouveauté, la prise en charge optimale des colonnes inspecteur. Un inspecteur est une colonne d’un contrôleur de vue scindée qui fournit des détails supplémentaires sur le contenu sélectionné. Aperçu utilise un inspecteur pour afficher les métadonnées à côté de la photo, dans la colonne secondaire. Lorsque le contrôleur de vue scindée est développé, la colonne inspecteur se trouve sur le bord arrière, à côté de la colonne secondaire.
Une fois réduit, le contrôleur de vue scindée s’adapte automatiquement et présente la colonne inspecteur sous forme de fenêtre.
Pour intégrer un inspecteur dans votre contrôleur de vue scindée, spécifiez un contrôleur de vue pour la colonne inspecteur. Lorsque le contrôleur de vue scindée apparaît pour la première fois, la colonne inspecteur est masquée. Demandez l’affichage pour afficher la colonne inspecteur. UISplitViewController est conçu pour être flexible. Il garantit la meilleure expérience de navigation possible avec votre app, quelle que soit sa taille. Un autre conteneur à votre disposition est UITabBarController. UITabBarController affiche plusieurs volets de contenu mutuellement exclusifs, dans la même zone. La barre d’onglets permet de passer rapidement d’un onglet à l’autre, tout en préservant l’état actuel dans chaque volet. De plus, l’apparence de la barre d’onglets s’adapte à chaque plate-forme.
Sur iPhone, la barre d’onglets est située en bas de la scène. Sur Mac, elle peut se trouver dans la barre d’outils ou s’afficher sous forme de barre latérale.
Sur Apple Vision Pro, elle s’affiche sous forme d’ornement sur le bord avant de la scène. Sur iPad, elle se trouve en haut de la scène, à côté des commandes de navigation. La barre d’onglets peut également se transformer en barre latérale, offrant ainsi un accès rapide à des collections de contenus. Les groupes d’onglets font apparaître des destinations supplémentaires dans la barre latérale. Par exemple, dans l’app Musique sur iPad, le groupe d’onglets Bibliothèque inclut Artistes, Albums et plus encore.
Lorsque la barre latérale est indisponible, le groupe Bibliothèque est une destination d’onglets.
UITabBarController propose une API pour gérer cette adaptation de manière transparente. Tout d’abord, dotez le groupe d’onglets d’un contrôleur de navigation. Lorsqu’un onglet Feuille du groupe d’onglets est sélectionné, son contrôleur de vue, ainsi que ceux de ses groupes ancêtres, sont poussés sur cette pile de navigation. Pour personnaliser les contrôleurs de vue poussés sur cette pile de navigation, implémentez la méthode de délégué UITabBarController, onglet displayedViewControllersFor. Dans cet exemple, lorsque l’onglet Bibliothèque ne peut pas être sélectionné, la méthode de délégué renvoie un tableau vide pour omettre le contrôleur de vue de l’onglet Bibliothèque de la pile.
Pour en savoir plus sur la façon dont UITabBarController offre la flexibilité nécessaire pour afficher une barre d’onglets ou une barre latérale, regardez la séance « Elevate your tab and sidebar experience in iPadOS » de la WWDC24. L’adoption de contrôleurs de vue de conteneur, tels que UISplitViewController et UITabBarController, est le meilleur moyen de garantir la flexibilité de votre app. Bien que ces conteneurs soient conçus pour prendre en charge un large éventail de tailles, il se peut que votre app ait besoin d’une taille minimale pour conserver ses fonctionnalités de base. Vous pouvez utiliser l’API UISceneSizeRestrictions pour exprimer la taille minimale souhaitée pour le contenu de votre scène. Le meilleur moment pour spécifier la taille minimale est lorsque la scène est sur le point de se connecter. Dans cet exemple, je spécifie une largeur minimale préférée de 500 points. Pour que votre app soit vraiment flexible, votre propre interface doit pouvoir s’adapter. Ensuite, je parlerai des API qui vous aideront à créer une interface adaptative. Une étape cruciale pour rendre votre interface adaptative consiste à s’assurer que le contenu reste dans la zone sûre. La zone sûre est une zone d’une vue qui est appropriée pour le contenu interactif ou important. Le contenu placé en dehors de cette zone risque d’être recouvert, par exemple par une barre de navigation ou une barre d’outils.
Le contenu peut également être masqué par l’interface du système, comme la barre d’état, ou même par des fonctionnalités de l’appareil, comme Dynamic Island.
La barre latérale ajoute une zone sûre non symétrique, insérée dans la colonne adjacente d’un contrôleur de vue scindée. L’arrière-plan peut s’étendre librement en dehors de la zone sûre, sous la barre latérale.
Le contenu, tel que la transcription du message, est positionné dans la zone sûr pour garantir sa visibilité. Les bulles de message sont insérées à partir des bords de la zone sûre à l’aide des marges de mise en forme. Cela garantit un espacement cohérent et une séparation visuelle nette de la barre latérale.
Chaque vue fournit des repères de mise en forme permettant d’appliquer des marges standard autour du contenu. Par défaut, les marges de mise en forme sont insérées dans la zone sûre. Dans cet exemple, je demande un guide de mise en forme pour positionner le contenu dans la vue de conteneur. J’utilise ensuite ce guide de mise en forme pour configurer les contraintes de la vue de contenu.
Dans iPadOS 26, les scènes bénéficient d’une nouvelle commande pour fermer, réduire et organiser la fenêtre, comme dans macOS. La commande de fenêtre s’affiche à côté du contenu de votre scène.
Une scène peut spécifier un style de commande de fenêtre préféré pour compléter son contenu. Pour spécifier une préférence, implémentez la méthode preferredWindowingControlStyle de UIWindowSceneDelegate pour la scène.
Les composants système, tels que UINavigationBar, s’adaptent automatiquement en organisant leurs vues secondaires autour de la commande de fenêtre. Votre interface doit également s’adapter à la commande de fenêtre, quel que soit son style.
Pour vous assurer que votre interface n’est pas masquée, utilisez un repère de disposition qui tient compte de la commande de fenêtre. Dans cet exemple, je demande un guide de marges de mise en forme avec une adaptation horizontale des coins. Ce guide de mise en forme est idéal pour le contenu de type barre au début d’une scène, qui doit être inséré à partir du bord arrière de la commande de fenêtre. J’utilise ensuite ce guide de mise en forme pour configurer les contraintes de la vue de contenu. Lorsque votre interface est adaptative, l’orientation de l’interface doit être redondante. Le redimensionnement de la scène, la rotation de l’appareil et les modifications de la disposition des fenêtres entraînent tous une modification de la taille de votre scène. Le verrouillage temporaire de l’orientation peut être bénéfique pour certaines catégories d’apps. Par exemple, un jeu de conduite peut vouloir verrouiller l’orientation lorsque l’appareil est censé tourner pour diriger un véhicule.
Lorsqu’un contrôleur de vue est visible, il peut préférer une orientation d’interface verrouillée. Pour indiquer une préférence, remplacez prefersInterfaceOrientationLocked dans votre sous-classe de contrôleur de vue. Chaque fois que cette préférence change, appelez setNeedsUpdateOfPrefersInterfaceOrientationLocked.
Pour observer le verrou d’orientation de l’interface, implémentez didUpdateEffectiveGeometry de la méthode UIWindowSceneDelegate. Ensuite, comparez si la valeur de isInterfaceOrientationLocked a changé. Pour que votre app soit vraiment adaptable, elle doit réagir rapidement au redimensionnement. Le dessin de certains éléments de l’interface de votre app peut nécessiter des ressources informatiques coûteuses.
C’est courant avec les jeux, où un certain nombre de ressources peuvent exiger un redimensionnement lorsque la scène change de taille. Il n’est pas nécessaire de redessiner chaque taille d’élément lors d’une interaction de redimensionnement. Dans cet exemple, isInteractivelyResizing est interrogé pour ne mettre à jour les éléments d’une nouvelle taille de scène qu’une fois l’interaction terminée.
Des apps flexibles permettent à chacun d’utiliser ses appareils comme bon lui semble. Ils offrent une expérience exceptionnelle dans une large gamme de tailles, ce qui leur permet d’être utilisés dans n’importe quelle orientation ou disposition. La clé Info.plist de UIRequiresFullscreen est un mode de compatibilité d’iOS 9 qui empêche le redimensionnement des scènes. UIRequiresFullscreen est obsolète et sera ignoré dans une prochaine version. Les apps adaptables n’ont pas besoin de cette clé et doivent la supprimer.
Il existe un autre mode de compatibilité, spécifiquement pour le nouveau matériel. Auparavant, lorsqu’un nouveau matériel était publié avec une taille d’écran différente, le système redimensionnait ou mettait en mode letterbox l’interface de votre app. Cette mise à l’échelle restait en place jusqu’à ce que vous créiez avec un SDK plus récent et soumettiez à nouveau votre app. Une fois votre app créée et soumise avec le SDK iOS 26, le système ne met plus à l’échelle ni avec des bandes noires l’interface de votre app pour une nouvelle taille d’écran.
Voici les bonnes pratiques pour garantir la flexibilité de votre app. Alors, quelle est l’étape suivante ? Adoptez le cycle de vie des scènes dans votre app pour garantir les bases solides d’une app flexible. Utilisez des contrôleurs de vue de conteneur pour gérer les composants de votre interface. Enfin, tirez parti d’API telles que les guides de mise en forme pour vous aider à créer une interface adaptative. J’ai hâte de voir vos apps gagner en flexibilité. Merci !
-
-
3:02 - Specify the scene configuration
// Specify the scene configuration @main class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, configurationForConnecting sceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { if sceneSession.role == .windowExternalDisplayNonInteractive { return UISceneConfiguration(name: "Timer Scene", sessionRole: sceneSession.role) } else { return UISceneConfiguration(name: "Main Scene", sessionRole: sceneSession.role) } } }
-
3:30 - Configure the UI
// Configure the UI class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? var timerModel = TimerModel() func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { let windowScene = scene as! UIWindowScene let window = UIWindow(windowScene: windowScene) window.rootViewController = TimerViewController(model: timerModel) window.makeKeyAndVisible() self.window = window } }
-
3:56 - Handle life cycle events
// Handle life cycle events class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? var timerModel = TimerModel() // ... func sceneDidEnterBackground(_ scene: UIScene) { timerModel.pause() } }
-
4:09 - Restore UI state
// Restore UI state class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? var timerModel = TimerModel() // ... func stateRestorationActivity(for scene: UIScene) -> NSUserActivity? { let userActivity = NSUserActivity(activityType: "com.example.timer.ui-state") userActivity.userInfo = ["selectedTimeFormat": timerModel.selectedTimeFormat] return userActivity } func scene(_ scene: UIScene restoreInteractionStateWith userActivity: NSUserActivity) { if let selectedTimeFormat = userActivity?["selectedTimeFormat"] as? String { timerModel.selectedTimeFormat = selectedTimeFormat } }
-
4:46 - Adapt for the split view controller layout environment
// Adapt for the split view controller layout environment override func updateConfiguration(using state: UICellConfigurationState) { // ... if state.traitCollection.splitViewControllerLayoutEnvironment == .collapsed { accessories = [.disclosureIndicator()] } else { accessories = [] } }
-
6:11 - Customize the minimum, maximum, and preferred column widths
// Customize the minimum, maximum, and preferred column widths let splitViewController = // ... splitViewController.minimumPrimaryColumnWidth = 200.0 splitViewController.maximumPrimaryColumnWidth = 400.0 splitViewController.preferredSupplementaryColumnWidth = 500.0
-
7:37 - Show an inspector column
// Show an inspector column let splitViewController = // ... splitViewController.setViewController(inspectorViewController, for: .inspector) splitViewController.show(.inspector)
-
9:19 - Managing tab groups
// Managing tab groups let group = UITabGroup(title: "Library", ...) group.managingNavigationController = UINavigationController() // ... // MARK: - UITabBarControllerDelegate func tabBarController( _ tabBarController: UITabBarController, displayedViewControllersFor tab: UITab, proposedViewControllers: [UIViewController]) -> [UIViewController] { if tab.identifier == "Library" && !self.allowsSelectingLibraryTab { return [] } else { return proposedViewControllers } }
-
10:25 - Preferred minimum size
// Specify a preferred minimum size class SceneDelegate: UIResponder, UIWindowSceneDelegate { func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { let windowScene = scene as! UIWindowScene windowScene.sizeRestrictions?.minimumSize.width = 500.0 } }
-
11:57 - Position content using the layout margins guide
// Position content using the layout margins guide let containerView = // ... let contentView = // ... let contentGuide = containerView.layoutMarginsGuide NSLayoutConstraint.activate([ contentView.topAnchor.constraint(equalTo: contentGuide.topAnchor), contentView.leadingAnchor.constraint(equalTo: contentGuide.leadingAnchor), contentView.bottomAnchor.constraint(equalTo: contentGuide.bottomAnchor) contentView.trailingAnchor.constraint(equalTo: contentGuide.trailingAnchor) ])
-
12:34 - Specify the window control style
// Specify the window control style class SceneDelegate: UIResponder, UIWindowSceneDelegate { func preferredWindowingControlStyle( for scene: UIWindowScene) -> UIWindowScene.WindowingControlStyle { return .unified } }
-
13:04 - Respect the window control area
// Respect the window control area let containerView = // ... let contentView = // ... let contentGuide = containerView.layoutGuide(for: .margins(cornerAdaptation: .horizontal) NSLayoutConstraint.activate([ contentView.topAnchor.constraint(equalTo: contentGuide.topAnchor), contentView.leadingAnchor.constraint(equalTo: contentGuide.leadingAnchor), contentView.bottomAnchor.constraint(equalTo: contentGuide.bottomAnchor), contentView.trailingAnchor.constraint(equalTo: contentGuide.trailingAnchor) ])
-
13:57 - Request orientation lock
// Request orientation lock class RaceViewController: UIViewController { override var prefersInterfaceOrientationLocked: Bool { return isDriving } // ... var isDriving: Bool = false { didSet { if isDriving != oldValue { setNeedsUpdateOfPrefersInterfaceOrientationLocked() } } } }
-
14:18 - Observe the interface orientation lock
// Observe the interface orientation lock class SceneDelegate: UIResponder, UIWindowSceneDelegate { var game = Game() func windowScene( _ windowScene: UIWindowScene, didUpdateEffectiveGeometry previousGeometry: UIWindowScene.Geometry) { let wasLocked = previousGeometry.isInterfaceOrientationLocked let isLocked = windowScene.effectiveGeometry.isInterfaceOrientationLocked if wasLocked != isLocked { game.pauseIfNeeded(isInterfaceOrientationLocked: isLocked) } } }
-
14:44 - Query whether the scene is resizing
// Query whether the scene is resizing class SceneDelegate: UIResponder, UIWindowSceneDelegate { var gameAssetManager = GameAssetManager() var previousSceneSize = CGSize.zero func windowScene( _ windowScene: UIWindowScene, didUpdateEffectiveGeometry previousGeometry: UIWindowScene.Geometry) { let geometry = windowScene.effectiveGeometry let sceneSize = geometry.coordinateSpace.bounds.size if !geometry.isInteractivelyResizing && sceneSize != previousSceneSize { previousSceneSize = sceneSize gameAssetManager.updateAssets(sceneSize: sceneSize) } } }
-
-
- 0:00 - Introduction
Rendez les apps UIKit flexibles et adaptables sur différentes tailles d’écran et plateformes à l’aide de scènes, de contrôleurs de vue de conteneur et d’autres API.
- 0:58 - Scènes
Les scènes représentent des instances distinctes de l’interface utilisateur d’une app. Chaque scène gère son état de manière indépendante et se reconnecte de manière transparente. Les scènes fournissent un contexte sur l’affichage de l’app, comme la taille de l’écran et la géométrie de la fenêtre. Dans la prochaine version importante succédant à iOS 26, l’adoption du cycle de vie UIScene sera obligatoire.
- 4:58 - Contrôleurs de vue de conteneur
Les contrôleurs de vue de conteneur tels que « UISplitViewController » et « UITabBarController » gèrent la disposition d’un ou plusieurs contrôleurs de vue enfants. Ils contribuent à rendre les apps flexibles, adaptables et personnalisables. Utilisez l’API UISceneRestrictions pour indiquer la taille minimale des scènes dans l’app.
- 10:45 - Adaptabilité
Les repères de mise en forme et les marges aident à positionner le contenu d’une app de manière cohérente dans la zone de sécurité de l’appareil. iPadOS 26 introduit un nouveau contrôle de fenêtre. Les apps peuvent spécifier « preferredWindowingControlStyle » et des guides de mise en forme pour prendre en charge ces commandes. Les interfaces utilisateur adaptatives doivent réagir rapidement aux changements de dimension et d’orientation, mais certaines apps peuvent ignorer « prefersInterfaceOrientationLocked » pour verrouiller temporairement l’orientation. Pour les opérations coûteuses en calcul, cochez « isInteractivelyResizing » pour effectuer les opérations au terme d’une interaction. « UIRequiresFullscreen » est obsolète.
- 15:39 - Compatibilité future
Avec le SDK iOS 26, les apps s’adaptent automatiquement à de nouvelles tailles d’écran sans nécessiter de mises à jour manuelles ou de nouvelles soumissions.
- 16:07 - Étapes suivantes
Pour créer une app flexible, respectez le cycle de vie des scènes, utilisez des contrôleurs de vue de conteneur et utilisez des API telles que des repères de mise en forme.