-
Plantez le décor avec SwiftUI dans visionOS
Découvrez de nouvelles API passionnantes pour améliorer les fenêtres, les volumes et les espaces immersifs de votre app visionOS. Affinez le comportement de vos scènes lorsqu'elles sont relancées ou verrouillées. Faites en sorte que les volumes s'adaptent à leur environnement grâce aux marges de découpe et aux alignements automatiques. Diffusez du contenu immersif de votre Mac vers Vision Pro. Améliorez vos apps UIKit existantes en intégrant des volumes et des espaces immersifs.
Chapitres
- 0:00 - Introduction
- 2:11 - Lancement et verrouillage
- 8:15 - Améliorations volumétriques
- 15:58 - Espace immersif
- 22:16 - Scene bridging
- 24:01 - Étapes suivantes
Ressources
- Adopting best practices for persistent UI
- Tracking accessories in volumetric windows
- Petite Asteroids: Building a volumetric visionOS game
- Canyon Crosser: Building a volumetric hike-planning app
Vidéos connexes
WWDC25
-
Rechercher dans cette vidéo…
-
-
4:10 - Disabling restoration
// Disabling restoration WindowGroup("Tools", id: "tools") { ToolsView() } .restorationBehavior(.disabled) -
4:36 - Disabling restoration in UIKit
// Disabling restoration windowScene.destructionConditions = [ .systemDisconnection ] -
5:02 - Specifying launch window
// Specifying launch window @AppStorage("isFirstLaunch") private var isFirstLaunch = true var body: some Scene { WindowGroup("Stage Selection", id: "selection") { SelectionView() } WindowGroup("Welcome", id: "welcome") { WelcomeView() .onAppear { isFirstLaunch = false } } .defaultLaunchBehavior(isFirstLaunch ? .presented : .automatic) // ... } -
6:39 - "suppressed" behavior
// "suppressed" behavior WindowGroup("Tools", id: "tools") { ToolsView() } .restorationBehavior(.disabled) .defaultLaunchBehavior(.suppressed) -
7:44 - Unique window
// Unique window @AppStorage("isFirstLaunch") private var isFirstLaunch = true var body: some Scene { // ... Window("Welcome", id: "welcome") { WelcomeView() .onAppear { isFirstLaunch = false } } .defaultLaunchBehavior(isFirstLaunch ? .presented : .automatic) WindowGroup("Main Stage", id: "main") { StageView() } // ... } -
10:24 - Surface snapping
// Surface snapping @Environment(\.surfaceSnappingInfo) private var snappingInfo @State private var hidePlatform = false var body: some View { RealityView { /* ... */ } .onChange(of: snappingInfo) { if snappingInfo.isSnapped && SurfaceSnappingInfo.authorizationStatus == .authorized { switch snappingInfo.classification { case .table: hidePlatform = true default: hidePlatform = false } } } } -
14:41 - Clipping margins
// Clipping margins @Environment(\.windowClippingMargins) private var windowMargins @PhysicalMetric(from: .meters) private var pointsPerMeter = 1 var body: some View { RealityView { content in // ... waterfall = createWaterfallEntity() content.add(waterfall) } update: { content in waterfall.scale.y = Float(min( windowMargins.bottom / pointsPerMeter, maxWaterfallHeight)) // ... } .preferredWindowClippingMargins(.bottom, maxWaterfallHeight * pointsPerMeter) } -
16:44 - World recenter
// World recenter var body: some View { RealityView { content in // ... } .onWorldRecenter { recomputePositions() } } -
17:58 - Progressive immersion style
// Progressive immersion style @State private var selectedStyle: ImmersionStyle = .progressive var body: some Scene { ImmersiveSpace(id: "space") { ImmersiveView() } .immersionStyle( selection: $selectedStyle, in: .progressive(aspectRatio: .portrait)) } -
18:37 - Mixed immersion style
// Mixed immersion style @State private var selectedStyle: ImmersionStyle = .progressive var body: some Scene { ImmersiveSpace(id: "space") { ImmersiveView() } .immersionStyle(selection: $selectedStyle, in: .mixed) .immersiveEnvironmentBehavior(.coexist) } -
20:14 - Remote immersive space
// Remote immersive space // Presented on visionOS RemoteImmersiveSpace(id: "preview-space") { CompositorLayer(configuration: config) { /* ... */ } } // Presented on macOS WindowGroup("Main Stage", id: "main") { StageView() } -
20:48 - 'CompositorLayer' is a 'CompositorContent'
// 'CompositorLayer' is a 'CompositorContent' struct ImmersiveContent: CompositorContent { @Environment(\.scenePhase) private var scenePhase var body: some CompositorContent { CompositorLayer { renderer in // ... } .onImmersionChange { oldImmersion, newImmersion in // ... } } } -
23:00 - Scene bridging
// Scene bridging import UIKit import SwiftUI // Declare the scenes class MyHostingSceneDelegate: NSObject, UIHostingSceneDelegate { static var rootScene: some Scene { WindowGroup(id: "my-volume") { ContentView() } .windowStyle(.volumetric) } } // Create a request for the scene let requestWithId = UISceneSessionActivationRequest( hostingDelegateClass: MyHostingSceneDelegate.self, id: "my-volume")! // Send a request UIApplication.shared.activateSceneSession(for: requestWithId)
-
-
- 0:00 - Introduction
Dans visionOS 26, vous pouvez utiliser de nouvelles API pour les scènes, les fenêtres, les volumes et les espaces immersifs. Elles vous permettront de créer des apps plus dynamiques et interactives. Parmi les nouvelles fonctionnalités, citons les API de cycle de vie, les améliorations volumétriques, « RemoteImmersiveSpace » pour la prévisualisation sur Apple Vision Pro et les API Scene Bridging pour les apps UIKit.
- 2:11 - Lancement et verrouillage
Les nouvelles API de visionOS 26 vous permettent de gérer le lancement des apps et la restauration des scènes. Vous pouvez ainsi créer des expériences plus immersives. Les utilisateurs peuvent désormais verrouiller des fenêtres, des volumes et des widgets dans des pièces spécifiques. Le contenu virtuel reste ainsi présent dans leur environnement physique. Le système rétablit de lui-même les fenêtres verrouillées dès qu’un utilisateur entre dans la pièce concernée. Cependant, vous pouvez bloquer cette restauration pour certains éléments temporaires, comme les écrans de bienvenue ou les menus contextuels en utilisant le modificateur « restorationBehavior(.disabled) ». Vous pouvez aussi personnaliser le démarrage de l’app en sélectionnant de manière dynamique la fenêtre à afficher selon l’état de l’app, grâce au modificateur « defaultLaunchBehavior ». Les fenêtres uniques, qui ne peuvent pas être dupliquées, sont désormais gérées par l’API Window, ce qui empêcher la duplication d’interfaces importantes, telles que les fenêtres de jeu ou les appels vidéo.
- 8:15 - Améliorations volumétriques
Plusieurs améliorations majeures ont été apportées aux volumes. Vous pouvez utiliser l’API « SurfaceSnappingInfo » pour surveiller quand les fenêtres et les volumes s’alignent sur des surfaces physiques, telles que des murs et des tables. Cette fonctionnalité offre des expériences plus immersives, car vous pouvez ajuster la scène en fonction de l’état d’alignement, par exemple en masquant des plateformes ou en ajustant des accessoires. ARKit peut fournir des détails sur la surface alignée à votre app, avec l’autorisation de l’utilisateur. La mise à jour étend également les fonctionnalités de présentation. Les éléments peuvent désormais provenir de différentes sources dans les volumes, les ornements et RealityKit, et bénéficier de traitements visuels spéciaux qui garantissent leur visibilité derrière le contenu 3D. Personnalisez le traitement visuel grâce au modificateur « presentationBreakthroughEffect ». De plus, grâce à la nouvelle API Clipping Margins, vous pouvez afficher du contenu non interactif en dehors des limites de la scène, ce qui améliore les effets visuels, tels que les cascades ou les nuages, tout en garantissant que le contenu principal reste centré et dégagé. Consultez la variable d’environnement « windowClippingMargins » pour vérifier si le système a accordé les marges.
- 15:58 - Espace immersif
Vous pouvez désormais réagir à un évènement de recentrage du monde, qui permet aux utilisateurs de recalibrer l’expérience de l’app autour d’eux. Utilisez le modificateur de vue « onWorldRecent » pour écouter cet évènement, puis recalculez et enregistrez les positions en fonction du nouveau système de coordonnées. visionOS 26 offre également de nouvelles options de personnalisation pour les styles d’immersion. Le style d’immersion progressive inclut désormais le format portrait, ce qui permet des expériences verticales et améliore le confort lors de la lecture de contenus à fort mouvement. Le style d’immersion mixte permet désormais au contenu de s’intégrer de manière transparente à l’environnement du système. Vous créez ainsi des scénarios plus immersifs. Utilisez le modificateur de scène « immersiveEnvironmentBehavior » avec le comportement « coexist » pour activer cette fusion. Grâce à « RemoteImmersiveSpaces », vous pouvez désormais importer vos apps sur macOS et de visualiser des environnements immersifs directement sur l’Apple Vision Pro. Cette fonctionnalité accélère les itérations et la collaboration. Utilisez « CompositorLayer » pour rendre du contenu avec Metal sur votre Mac, puis affichez-le sur votre Apple Vision Pro. L’arrivée du générateur « CompositorContent » permet de tirer pleinement parti de SwiftUI avec « CompositorLayer ». Cette nouveauté simplifie considérablement la création et le pilotage d’expériences immersives, que ce soit à distance ou en local. Elle offre également un accès pratique aux variables d’environnement, la possibilité d’ajouter des modificateurs et l’utilisation de variables d’état.
- 22:16 - Scene bridging
La fonctionnalité Scene Bridging de visionOS 26 vous permet d’ajouter des volumes SwiftUI et des espaces immersifs à des apps UIKit existantes. Grâce à l’extension de « UIHostingSceneDelegate », vous pouvez créer des scènes SwiftUI et les demander à l’aide de « UISceneSessionActivationRequest ». Les apps, telles que Safari peuvent ainsi utiliser la navigation spatiale et d’autres apps peuvent aussi tirer parti des nouvelles fonctionnalités de visionOS.
- 24:01 - Étapes suivantes
L’app de démonstration permet aux utilisateurs de concevoir des scènes verrouillées et alignées sur des surfaces, qu’ils peuvent ensuite déverrouiller et manipuler à distance depuis leur Mac. Prenez le temps d’analyser vos apps pour vous assurer qu’elles exploitent au maximum ces nouvelles fonctionnalités.