View in English

  • Global Nav Open Menu Global Nav Close Menu
  • Apple Developer
Search
Cancel
  • Apple Developer
  • News
  • Discover
  • Design
  • Develop
  • Distribute
  • Support
  • Account
Only search within “”

Quick Links

5 Quick Links

Videos

Abrir menú Cerrar menú
  • Colecciones
  • Temas
  • Todos los videos
  • Información

Más videos

  • Información
  • Resumen
  • Transcripción
  • Código
  • Prepara el escenario con SwiftUI en visionOS

    Descubre nuevas y emocionantes API para mejorar ventanas, volúmenes y espacios envolventes en tu app de visionOS. Ajusta el comportamiento de tus escenas cuando se reinician o se bloquean en un lugar. Haz que los volúmenes se adapten a tu entorno con márgenes de recorte y ajuste. Transmite contenido envolvente desde la Mac a Vision Pro. Mejora tus apps existentes basadas en UIKit con volúmenes y espacios envolventes.

    Capítulos

    • 0:00 - Introducción
    • 2:11 - Lanzamiento y bloqueo
    • 8:15 - Mejoras volumétricas
    • 15:58 - Espacio envolvente
    • 22:16 - Puente de escena
    • 24:01 - Próximos pasos

    Recursos

    • Adopting best practices for persistent UI
    • Canyon Crosser: Building a volumetric hike-planning app
    • Petite Asteroids: Building a volumetric visionOS game
    • Tracking accessories in volumetric windows
      • Video HD
      • Video SD

    Videos relacionados

    WWDC25

    • Mejor juntos: SwiftUI y RealityKit
    • Novedades de widgets
    • Novedades del renderizado de Metal para apps inmersivas
  • Buscar este video…

    Hola, soy Miguel, ingeniero del equipo SwiftUI. En este video, veremos algunas de las nuevas capacidades increíbles agregadas a las escenas en visionOS 26. Aprenderemos a hacer escenarios nosotros.

    visionOS tiene tres tipos de escenas: ventanas, volúmenes y espacios envolventes. Las apps combinan estos elementos para crear experiencias únicas y emocionantes.

    Hoy veremos nuevas API que se aplican a los tres tipos y algunas que están más centradas en volúmenes y espacios envolventes. Mis amigos Maks, Amanda y Trevor trabajan en algunas mejoras interesantes en BOTanist, un juego sobre ayudar a un robot a cultivar hermosas plantas en un jardín flotante.

    Yo he trabajado en mi propia app, creando escenas y escenografía para que nuestros amigos robots les den vida a personajes de Shakespeare y se adentren en el mundo de la actuación.

    Al abrir mi app, aparece una pantalla de selección de escenario. Creemos uno nuevo.

    Ahora puedo diseñar la escena moviendo el BOTanist por todo el escenario.

    Con a esto, puedo tener un amigo robot que actúe en mis obras favoritas, como Robo y Julieta.

    Veamos cómo mejorar mi app con las nuevas API de escena de visionOS 26.

    Primero, veremos las nuevas API de ciclo de vida para definir comportamientos al iniciar y bloquear ventanas en habitaciones.

    Segundo, introduciré nuevas mejoras volumétricas que se adaptan al entorno de las personas.

    Luego, agregaré un RemoteImmersiveSpace para una vista previa de mi escena en Apple Vision Pro desde una app de macOS.

    Después, para las apps de UIKit existentes, finalizamos agregando increíbles experiencias volumétricas y envolventes con las nuevas API de interconexión de escenas.

    Empecemos con lanzamiento y el bloqueo.

    visionOS 26 incorpora algunas API del ciclo de vida de macOS que te servirán bastante. Veremos las API para administrar la restauración de escenas e inicio de la app, como una API para crear ventanas únicas.

    En visionOS 26, las personas pueden conservar ventanas, volúmenes e incluso los nuevos widgets bloqueándolos en salas específicas de su entorno físico.

    Esto ayuda a que el contenido virtual se sienta presente en su espacio. Estas ventanas se vinculan con la sala en la que se usaron.

    Regresa a esa sala más tarde y las ventanas volverán a la vida.

    La restauración de la escena es increíble. Puedo tener todas mis ventanas cerca y volver a ellas cuando quiera.

    En general, la gente espera poder bloquear todas sus ventanas en su lugar y que el sistema las restaure. Prefiero la restauración para la mayoría de las escenas. Sistema lo hará automáticamente.

    Sin embargo, para algunas ventanas, tal vez no tenga sentido conservarlas así.

    Considera deshabilitar la restauración de escena de elementos transitorios, como una pantalla de bienvenida, una UI según el contexto o una ventana de herramientas vinculada a un estado específico o acciones únicas completas, como un mensaje de inicio de sesión.

    Agregué un modo envolvente para que la gente pueda apreciar completamente al mejor robot en acción. La barra de herramientas se separa en otra ventana frente a ellos, facilitando el acceso a los controles del escenario en la inmersión.

    Los espacios envolventes no se restauran.

    Entonces, al regresar a esta sala, el espacio envolvente no volverá.

    Sin embargo, si alguien hubiera bloqueado la ventana de herramientas en su espacio, aparecería sola sin nada que modificar.

    Para evitar este estado inesperado, agrego el modificador restorationBehavior(.disabled) a mi WindowGroup para elegir explícitamente que la ventana de herramientas no se restaure y se bloquee en su lugar.

    Cuando vuelvo a esta sala más tarde, la ventana adicional no regresa.

    Al iniciar la app se muestra la ventana para comenzar de nuevo.

    En UIKit, puedes deshabilitar la restauración de tus escenas de UI con la nueva API destructionConditions con una propiedad .systemDisconnection. Consulta la documentación para más información.

    En algunos casos, tu app podría beneficiarse al cambiar dinámicamente con qué escena comenzar.

    Por ejemplo, quiero agregar una ventana cuando se inicie la app para saludar a la gente antes de la selección.

    Para personalizar qué ventana mostrar al iniciar según el estado de mi app, puedo usar el modificador defaultLaunchBehavior.

    Aquí, priorizaré la ventana de bienvenida marcándola como presentada si es la primera vez que se inicia la app.

    Puedo desactivar este valor una vez que aparezca esa ventana, ya que ya no necesitaré mostrarla.

    Considera que el rol de la ventana de inicio elegida debe coincidir con la propiedad de rol de sesión de escena predeterminado preferido en el manifiesto de escena de la app de Info.plist.

    Eso significa que si defino mi rol de sesión de escena por defecto en Ventana, el sistema solo considerará las escenas de ventana normales durante el inicio de la app.

    En ese caso, los volúmenes se ignorarán, incluso si intento priorizarlos con defaultLaunchBehavior. Recuerda hacer coincidir la escena deseada con ese rol de la sesión.

    El modificador defaultLaunchBehavior tiene un truco adicional bajo la manga que puede servirnos.

    Hablé sobre cómo no quiero que el panel de herramientas regrese cuando vuelvo a una sala y cómo podría usar restorationBehavior para solucionarlo. Tengo un problema aquí.

    Actualmente, si descarto el espacio envolvente presionando la corona y cierro la ventana Herramientas, esta ventana regresará cuando inicie la app nuevamente.

    Esto nos deja en el mismo estado inesperado que tendría la restauración.

    Quiero reanudar la app desde un estado seguro empezando con una ventana de creación de escenario.

    Puedo hacer esto agregando el modificador defaultLaunchBehavior(.suppressed) a mi ventana de herramientas. Esto le indica que no vuelva a mostrar esta ventana al reiniciar la app desde el Inicio.

    En general, es preferible usar .suppressed defaultLaunchBehavior en escenas secundarias para que la gente no quede atrapada en un estado inesperado.

    En UIKit, puedes lograr el mismo comportamiento agregando la opción userInitiatedDismissal a las destructionConditions de tu UIScene.

    visionOS 26 también agrega soporte para crear ventanas únicas.

    Son ventanas que no se pueden duplicar. Solo puede existir una instancia a la vez.

    Al igual que en Mac, las defines usando la API de Window en lugar de WindowGroup.

    Úsalas para evitar la duplicación de interfaces importantes, como una ventana de juego o una videollamada.

    O úsalas para proporcionar una funcionalidad complementaria que no requiera más de una instancia.

    No necesito más de una instancia de la ventana. Así que la reemplazaré con una ventana única.

    Pero conservaré el volumen del escenario principal como un WindowGroup para permitir la creación de varios escenarios simultáneamente.

    Asombroso. El ciclo de vida de mi app es mejor. Personalizamos qué ventanas se muestran al bloquearse y durante el inicio. Y nos aseguramos de que las ventanas fueran únicas.

    Hay una serie de nuevas mejoras en los volúmenes en visionOS 26 que pueden ayudarte a llevar tus volúmenes a profundidades aún mayores.

    Hablaré de la nueva función de ajuste de superficies, de los avances en las presentaciones y de la API de márgenes de recorte.

    Empecemos.

    Como novedad en visionOS 26, las personas pueden adaptar ventanas y volúmenes a su entorno físico. Pueden hacerlo moviendo suavemente la ventana cerca de la superficie. Para las ventanas restaurables, esto las bloquea para estabilidad.

    Los usuarios pueden unir atrás de las ventanas a superficies verticales, como la pared. También pueden ajustar la parte inferior de los volúmenes a superficies horizontales, como el piso o una mesa.

    Y los widgets, que son nuevos en visionOS 26, se pueden ajustar a cualquier tipo.

    Obtén más información sobre cómo agregar widgets a tu app de visionOS en "Novedades en widgets". Para ventanas y volúmenes, puedes obtener información sobre el evento de ajuste.

    Con mi app, puedo ajustar el volumen a una mesa y anclarlo horizontalmente.

    Ya es un comienzo. Pero, quisiera que el escenario se sienta presente en el espacio. Quiero que el robot se coloque sobre la mesa cuando el volumen se ajuste.

    Podemos obtener información sobre el estado de ajuste utilizando la nueva API SurfaceSnappingInfo.

    La API nos proporciona una propiedad isSnapped simple para saber el estado de ajuste general de nuestra ventana.

    Para casos prácticos más avanzados, podemos obtener la clasificación ARKit de superficie ajustada. Este nivel de detalle requiere permiso del usuario. Te mostraré cómo.

    Para habilitar información detallada de la superficie ajustada, primero debo establecer la clave 'La app desea información detallada de la superficie' en SÍ, así como la opción 'Descripción de uso de detección mundial de privacidad' con una descripción que aparecerá cuando se solicite permiso.

    Estas dos claves se configuran en el Info.plist de la app.

    Una vez hecho esto, puedo ir al código.

    Aquí, obtengo el surfaceSnappingInfo del entorno.

    En onChange, verifico si la escena está ajustada. Y compruebo si estoy autorizado para acceder a la clasificación de la superficie de ajuste.

    Al verificar el authorizationStatus se le solicitará automáticamente permiso a la persona si se necesita.

    Ahora, cuando esté ajustada a una mesa, quiero ocultar la plataforma debajo del escenario. Uso variable de estado para monitorearlo.

    Con estos cambios, puedo adaptar mi volumen a una mesa y el robot puede actuar con toda el alma en mi propio entorno. ¡Impresionante!

    Hice que al caminar alrededor de la mesa se oculten las paredes que me estorban, para que siempre pueda ver dentro de volumen.

    Lo hice reaccionando a los cambios en el punto de vista de la escena con el modificador onVolumeViewpointChange.

    Mira cómo Owen lo agregó a BOTanist en "Adéntrate en volúmenes y espacios envolventes" de WWDC24 para obtener más información.

    Quiero que la gente pueda colocar utilería por todo el escenario. Agrego unaa ventana emergente en barra de volumen con distinta utilería.

    ¡Impresionante! Finalmente, puedo recrear La Tragedia del Rey Gear.

    Antes las presentaciones solo eran compatibles con Windows.

    Con visionOS 2.4 es compatible para presentaciones anidadas, permitiendo ventanas emergentes desde hojas o menús contextuales presentados desde adornos.

    Ahora, con visionOS 26, las presentaciones ganaron un nuevo conjunto de fuentes. Puedes presentar desde dentro de volúmenes, adornos de volúmenes, archivos adjuntos a RealityViews o directamente en RealityKit con PresentationComponent.

    Para obtener más información sobre el uso de presentaciones en RealityKit con archivos adjuntos y PresentationComponent, consulta "Better Together: SwiftUI y RealityKit". Esto no se limita a un pequeño subconjunto. Todo tipo de presentaciones disponibles: menús, información de herramientas, ventanas emergentes, hojas, alertas y diálogo de confirmación.

    Consulta los documentos para aprender a crear las presentaciones con SwiftUI.

    Todas las presentaciones tienen tratamientos visuales especiales para que se veancuando están ocultas por 3D.

    Predeterminadamente, la presentación se mezclará sutilmente con contenido oculto.

    Sin embargo, esto se puede personalizar para que destaque o se oculte detrás del contenido oculto.

    Utiliza las opciones sutil, prominente o ninguna para personalizar esto.

    Estas opciones se pueden aplicar a las presentaciones con el modificador presentationBreakthroughEffect.

    Para elementos que no sean presentaciones, puedes lograr el mismo efecto con modificador breakthroughEffect.

    Con las presentaciones, puedo agregar UI personalizada donde sea. Intentemos agregar más.

    Agregué otro menú para cambiar decoración de escenario. Con esto, puedo transportar a nuestro amigo robot lejos del viejo teatro a una isla tropical. ¡Perfecto para La Tempestad!

    Este conjunto tiene potencial. Pero, podría tener un poco más de dinamismo. ¿Qué tal una cascada? Ah, y unas nubes estruendosas.

    Aun así, quiero asegurarme de que estos no ocupen el centro de la acción. Puedo usar los Márgenes de recorte.

    Con Volumes, la nueva API preferredWindowClippingMargins te permite renderizar contenido fuera de los límites de tu escena.

    Este contenido no es interactivo. Debes usarlo solo para darle un toque visual.

    Es posible que el sistema no permita estos límites. Para tener esto en cuenta, lee los márgenes permitidos con la variable de entorno windowClippingMargins.

    Veámoslo en acción.

    Puedo especificar mis márgenes de recorte deseados con la API preferredWindowClippingMargins. Quiero márgenes en la parte inferior.

    Convierto mi maxWaterfallHeight, que está en metros, en puntos multiplicándolo por el factor pointsPerMeter que obtuve de PhysicalMetric.

    Luego, leo los márgenes permitidos con la variable de entorno windowClippingMargins.

    Puedo reajustar mi cascada para que se renderice dentro de los márgenes.

    Tomo el mínimo de los márgenes y la altura de la cascada para representar siempre todo el modelo de la cascada, sin importar lo que se haya permitido.

    Y así comienza. Eso se ve mucho mejor. Las nubes dan un toque agradable de tormenta, y la cascada aparece bajo la placa base sin desplazar el contenido hacia arriba, manteniendo nuestra atención en la isla y su robot.

    Ojalá el BOTanist esté engrasado.

    Con esto, nuestra última producción teatral se siente más real que nunca. El contenido se adapta con ajustes y márgenes de recorte al espacio físico. Y con las presentaciones, puedo diseñar interfaces impactantes para crear la escena perfecta.

    Veamos qué puedo hacer para mejorar la experiencia envolvente de app.

    Los espacios envolventes sumergen experiencias espaciales en entorno. Y visionOS 26 presenta nuevas y fantásticas formas de hacer aún más con los espacios envolventes.

    Presentaré un evento de reubicación mundial, nuevas capacidades con estilos de inmersión, espacio envolvente remoto en macOS y avances en los espacios envolventes basados en Compositor para renderizar con Metal. Al navegar en espacio, las personas pueden presionar la corona digital para ubicar la experiencia de app a su alrededor.

    Si tu app utiliza datos de ARKit, esto puede invalidar posiciones que hayas almacenado para uso posterior.

    Puedes escuchar el evento de reubicación mundial con el nuevo modificador de vista onWorldRecenter para recibir alertas al respecto.

    Esto ayuda para calcular y almacenar posiciones según el sistema de coordenadas.

    visionOS 26 incorpora algunas nuevas personalizaciones para los diferentes estilos de inmersión para espacios envolventes.

    El estilo de inmersión progresiva es excelente para presentar un espacio envolvente y mantener a las personas conectadas con el mundo.

    El contenido envolvente se presenta dentro de un portal que puede cambiar de tamaño girando la corona digital.

    Esta gama de inmersión se puede personalizar en el estilo de inmersión progresiva.

    En visionOS 26, también puedes personalizar la relación de aspecto de este portal. Puedes usar la relación de aspecto horizontal existente o la nueva relación de aspecto vertical.

    Considera usar la relación de aspecto vertical para experiencias verticales, como cuando llevas tus juegos de iPhone a Apple Vision Pro o para experiencias que tengan un alto grado de movimiento, ya que tener entornos estables en la periferia ayuda a que la gente se sienta más cómoda.

    Puedes especificar esta relación de aspecto con parámetro para estilo progresivo, como harías con el rango de inmersión.

    Además del estilo progresivo, también hay una nueva personalización para espacios envolventes en el estilo de inmersión mixta.

    Al configurar el estilo de inmersión como mixto, el contenido envolvente se fusiona con el entorno de personas.

    Este es el estilo de mi app.

    En visionOS 26, el contenido espacial envolvente también puede integrarse con los del sistema. Esto significa que puedo ver la última producción de mi robot mientras estoy en la luna.

    Usa el modificador de escena immersiveEnvironmentBehavior con el comportamiento coexistente para permitir esto.

    Hazlo si tu espacio envolvente mixto no necesita que usuarios sean conscientes del entorno del mundo real.

    Me encanta la utilería que agregué a mi app, pero sé que la gente querrá traer sus propios modelos al crear nuevas escenas. Podrían crear modelos en las mejores apps macOS.

    Para facilitar el uso de estos modelos directamente desde su Mac, lleve mi app a macOS con las mismas capacidades de creación de escenarios.

    Para una iteración más rápida, ¿no sería mejor si la gente tuviera una vista previa de sus escenas como un espacio envolvente sin llevar el escenario de macOS a visionOS?

    visionOS 26 y macOS Tahoe agregan RemoteImmersiveSpaces para que pueda hacer exactamente eso. Con espacios envolventes remotos, puedes usar CompositorLayer para renderizar contenido con Metal usando el código de la app y los recursos de tu Mac y mostrarlo como una experiencia envolvente en tu Vision Pro.

    Veamos cómo funciona en mi app.

    En mi app de Mac, creé un nuevo espacio envolvente usando Metal y agregué un botón "Vista previa en Vision Pro".

    Si hago clic aquí me pide que elija un dispositivo VisionPro destino.

    En mi Vision Pro, aceptaré la solicitud de conexión.

    Y así, mi ImmersiSpace se abre y puedo ver la nueva utilería que agregué en el último espectáculo de mi robot.

    Hice esto agregando una escena RemoteImmersiveSpace que contiene mi CompositorLayer.

    Esto se presentará en visionOS, mientras que el resto de mis escenas, como mi escenario principal, se presentarán directamente en Mac.

    Para conocer más sobre cómo adaptar CompositorLayer y ARKitSession a un dispositivo Vision Pro remoto, consulta "Novedades en el renderizado de Metal para apps envolventes". Con CompositorLayer en mi espacio envolvente remoto puedo crear experiencias envolventes con Metal de forma muy eficiente.

    Sin embargo, CompositorLayer no es una Vista y, por lo tanto, no se puede usar en contextos que requieren Vistas, como mi ImmersiveContent.

    Esto significaba que las variables de entorno y los modificadores de vista no estaban en CompositorLayer.

    visionOS 26 agrega un nuevo tipo de generador CompositorContent, que te permite usar todo el poder de SwiftUI con CompositorLayer.

    Ahora puedes acceder a variables de entorno, agregar modificadores o usar variables de estado tal como lo haces con las vistas de SwiftUI.

    CompositorContent incorpora una gran cantidad de variables de entorno útiles, como scenePhase y openWindow, y algunos modificadores como onImmersionChange y onWorldRecenter.

    Todo esto hace que CompositorLayer sea mucho más potente para usar tanto en espacios envolventes remotos como en los regulares que se ejecutan directamente en visionOS.

    Actualizar mi app para usar CompositorContent fue una excelente manera de volver a revisar algunos de los modificadores de Espacio envolvente disponibles para mí y ver cómo usarlos en mi app.

    Las novedades de espacios envolventes. Tenemos un evento de reubicación mundial, nuevas personalizaciones para los estilos de inmersión, espacios envolventes desde Mac con RemoteImmersiveSpace y CompositorContent.

    Mi app se ve increíble con todas estas capacidades. De hecho, creo que quiero agregar algunas interesantes experiencias volumétricas a más apps.

    Sin embargo, algunas de mis apps se crearon con UIKit, y UIKit no admite volúmenes ni espacios envolventes. Pero ahora sí con la interconexión de escenas.

    Con la interconexión de escenas puedes llevar las apps de UIKit existentes a la siguiente dimensión agregando volúmenes de SwiftUI y espacios envolventes.

    Considera Safari. Usa vistas de SwiftUI, pero está creada con el ciclo de vida de UIKit.

    Safari optimiza la interconexión de escenas para función de Navegación espacial.

    Veamos cómo podemos hacerlo.

    Para unir una escena de SwiftUI con mi app UIKit, comienzo creando un tipo de clase que se extiende desde UIHostingSceneDelegate.

    Con este tipo, puedo declarar mis escenas de SwiftUI en la propiedad rootScene usando la sintaxis familiar del cuerpo de la escena.

    Ahora puedo solicitar esta escena como lo haría con cualquier otra escena de UIKit creando una UISceneSessionActivationRequest.

    En este caso, paso mi clase delegada de alojamiento, que declara mis escenas y el ID de la escena que me gustaría abrir.

    Todo lo que queda es enviar esta solicitud con activateSceneSession.

    También puedes responder a eventos externos configurando tu clase delegada de alojamiento en configurationForConnecting.

    Esta API también viene con una API de AppKit correspondiente para conectar escenas de SwiftUI con tus apps de AppKit de macOS existentes.

    Mi app ahora aprovecha al máximo las nuevas capacidades de visionOS 26, como bloquearse en un lugar, ajustarse a superficies y abrirse de forma remota desde una Mac. Me emociona enseñarles a mis amigos.

    Ahora, echa una mirada a tus apps. Audita tus escenas y asegúrate de aprovechar al máximo el bloqueo en lugar y la restauración.

    Adapta tus escenas al entorno de las personas con márgenes de ajuste y recorte.

    Y sumerge el contenido de tu app de macOS en Vision Pro con espacios envolventes remotos.

    El telón cae, pero en nuestra app, el espectáculo continúa, una escena a la vez. Gracias por mirar.

    • 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 - Introducción
    • En visionOS 26 puedes usar nuevas API para escenas ・€・ ventanas, volúmenes y espacios envolventes ・€・ lo que te permite crear apps más dinámicas e interactivas. Las nuevas funcionalidades incluyen API de ciclo de vida, mejoras volumétricas, '“RemoteImmersiveSpace” para obtener una vista previa en el Apple Vision Pro y API de conexión de escenas para apps de UIKit.

    • 2:11 - Lanzamiento y bloqueo
    • Las nuevas API en visionOS 26 te permiten administrar el inicio de la app y la restauración de escenas, y te permiten crear experiencias más envolventes. Las personas ahora pueden bloquear ventanas, volúmenes y widgets en salas específicas, lo que permite que el contenido virtual persista en su entorno físico. El sistema restaura automáticamente las ventanas bloqueadas cuando alguien regresa a la sala asociada, pero puedes deshabilitar la restauración de elementos transitorios como pantallas de bienvenida o IU dependiente del contexto usando el modificador “restorationBehavior(.disabled).” También puedes personalizar el comportamiento de inicio de la app, eligiendo dinámicamente qué ventana mostrar según el estado de la app con el modificador “defaultLaunchBehavior.” La API de ventana ahora admite ventanas únicas que no se pueden duplicar para evitar la duplicación de interfaces importantes, como ventanas de juegos o videollamadas.

    • 8:15 - Mejoras volumétricas
    • Ahora hay varias mejoras clave para los volúmenes. Puedes usar la API “SurfaceSnappingInfo” para monitorear cuándo las ventanas y los volúmenes se ajustan a superficies físicas, como paredes y mesas. Esta funcionalidad permite experiencias más envolventes porque puedes ajustar la escena según el estado de anclaje, como ocultar plataformas o modificar elementos. ARKit puede proporcionar detalles sobre la superficie a tu app, con el permiso de los usuarios. La actualización también amplía las capacidades de presentación, permitiendo que se originen desde varias fuentes dentro de volúmenes, adornos y RealityKit, con tratamientos visuales especiales para garantizar que permanezcan visibles detrás del contenido 3D. Personaliza el tratamiento visual con el modificador “presentationBreakthroughEffect.” Además, al usar la nueva API Clipping Margins, puedes renderizar contenido no interactivo fuera de los límites de los volúmenes de la escena, mejorando los efectos visuales como cascadas o nubes mientras garantizas que el contenido principal permanezca enfocado y sin obstrucciones. Lee la variable de entorno “windowClippingMargins” para verificar si el sistema otorgó los márgenes.

    • 15:58 - Espacio envolvente
    • Ahora puedes responder a un evento de recentrado del mundo, lo que permite que las personas recalibren la experiencia de la app a su alrededor. Usa el modificador de vista “onWorldRecent” para escuchar este evento y volver a calcular y almacenar posiciones según el nuevo sistema de coordenadas. visionOS 26 también brinda nuevas personalizaciones para los estilos de inmersión. El estilo de inmersión progresiva ahora incluye el formato vertical, que permite experiencias en orientación vertical y mejora la comodidad durante contenido con mucho movimiento. El estilo de inmersión mixta ahora permite que el contenido se combine perfectamente con los entornos del sistema, creando escenarios más envolventes. Usa el modificador de escena “immersiveEnvironmentBehavior” con el comportamiento “coexistir” para habilitar esta combinación. Ahora puedes llevar tus apps a macOS y obtener una vista previa de las escenas directamente como espacios envolventes en el Apple Vision Pro usando “RemoteImmersiveSpaces.” Esta funcionalidad permite una iteración y colaboración más rápidas. Usa “CompositorLayer” para renderizar contenido con Metal en la Mac y mostrarlo en el Apple Vision Pro. La incorporación del tipo de constructor “CompositorContent” significa que puedes usar todo el potencial de SwiftUI con “CompositorLayer”, lo que facilita la creación y administración de experiencias envolventes, tanto remotas como locales, además de permitir el acceso a variables de entorno, la app de modificadores y el uso de variables de estado.

    • 22:16 - Puente de escena
    • Scene Bridging en visionOS 26 permite agregar volúmenes SwiftUI y espacios envolventes a las apps UIKit existentes. Al extender “UIHostingSceneDelegate”, puedes crear escenas SwiftUI y solicitarlas mediante “UISceneSessionActivationRequest”, lo que permite que apps como Safari implementen navegación espacial y otras apps aprovechen las nuevas capacidades de visionOS.

    • 24:01 - Próximos pasos
    • La app de ejemplo permite a las personas crear escenas que se bloquean en un lugar, se ajustan a las superficies y se abren de forma remota desde la Mac. Revisa tus apps y asegúrate de que aprovechen al máximo estas nuevas capacidades.

Developer Footer

  • Videos
  • WWDC25
  • Prepara el escenario con SwiftUI en visionOS
  • Open Menu Close Menu
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • Icon Composer
    • SF Symbols
    Open Menu Close Menu
    • Accessibility
    • Accessories
    • App Store
    • Audio & Video
    • Augmented Reality
    • Business
    • Design
    • Distribution
    • Education
    • Fonts
    • Games
    • Health & Fitness
    • In-App Purchase
    • Localization
    • Maps & Location
    • Machine Learning & AI
    • Open Source
    • Security
    • Safari & Web
    Open Menu Close Menu
    • Documentation
    • Sample Code
    • Tutorials
    • Downloads
    • Forums
    • Videos
    Open Menu Close Menu
    • Support Articles
    • Contact Us
    • Bug Reporting
    • System Status
    Open Menu Close Menu
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles
    • Feedback Assistant
    Open Menu Close Menu
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program
    • News Partner Program
    • Video Partner Program
    • Security Bounty Program
    • Security Research Device Program
    Open Menu Close Menu
    • Meet with Apple
    • Apple Developer Centers
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Academies
    • WWDC
    Get the Apple Developer app.
    Copyright © 2025 Apple Inc. All rights reserved.
    Terms of Use Privacy Policy Agreements and Guidelines