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
  • Haz que tu app UIKit sea más flexible

    Descubre cómo tu app UIKit puede volverse más flexible en iPhone, iPad, Mac y Apple Vision Pro mediante el uso de escenas y controladores de vista de contenedor. Aprende a liberar todo el potencial de tu app mediante la transición de un ciclo de vida centrado en la app a uno basado en escenas, que incluye un redimensionamiento de ventana y una multitarea mejorados. Explora las mejoras de UISplitViewController, como el cambio de tamaño de columnas interactivo y soporte de primera clase para columnas de inspector. También haz que tus vistas y controles sean más adaptables con nuevas API de diseño.

    Capítulos

    • 0:00 - Introducción
    • 0:58 - Escenas
    • 4:58 - Controladores de vista de contenedor
    • 10:45 - Adaptabilidad
    • 15:39 - Compatibilidad futura
    • 16:07 - Próximos pasos

    Recursos

    • TN3187: Migrating to the UIKit scene-based life cycle
    • UIKit updates
      • Video HD
      • Video SD

    Videos relacionados

    WWDC25

    • Novedades de UIKit

    WWDC24

    • Elevate your tab and sidebar experience in iPadOS
  • Buscar este video…

    Hola, te doy la bienvenida a “Make your UIKit app more flexible”. Soy Alexander MacLeod, ingeniero del equipo de UIKit. Una app flexible ofrece una experiencia increíble en una variedad de tamaños y plataformas. Mantiene una experiencia de navegación familiar e intuitiva en cualquier tamaño. En este video, hablaré sobre algunas de las mejores prácticas para garantizar que tu app sea flexible. Primero, repasaré los conceptos básicos de las escenas y explicaré cómo son fundamentales para una app flexible. Luego, analizaré los controladores de vista de contenedor, como UISplitViewController y UITabBarController, y exploraré cómo aportan flexibilidad a tu app. Por último, hablaré sobre las API para ayudarte a construir una IU adaptativa y verdaderamente flexible. Comenzaré con las escenas. Una escena es una instancia de la IU de su app. Contiene los controladores de vista y las vistas de tu app. Las escenas proporcionan ganchos para manejar datos externos, como una URL para realizar un enlace profundo a una sección de la IU de tu app.

    Cada escena guarda y restaura de forma independiente el estado de la IU. Una escena determina las mejores oportunidades para solicitar el estado actual, antes de persistirlo en el disco. Puedes consultar el estado anterior de la IU cuando una escena se vuelve a conectar. Esto te permite restaurar tu escena exactamente como era antes. Las escenas también proporcionan contexto sobre cómo se muestra la app, incluidos detalles sobre la pantalla y la geometría de la ventana. Puedes tener varias escenas, cada una con su propio ciclo de vida y estado. Los tipos de escenas dedicados están diseñados para encapsular experiencias distintas. Por ejemplo, una app de mensajería puede tener una escena de redacción dedicada para enviar mensajes nuevos. En iOS 26, ahora puedes combinar los tipos de escenas de SwiftUI y UIKit en una sola app. Consulta “What’s new in UIKit” para obtener más información. La portabilidad que proporcionan las escenas es la base perfecta para una app flexible.

    Como las escenas son vitales para garantizar la flexibilidad, pronto será obligatorio adoptar el ciclo de vida UIScene. En la próxima versión importante posterior a iOS 26, se requerirá el ciclo de vida de UIScene al compilar con el último SDK.

    Si bien se recomienda admitir múltiples escenas, solo se requiere la adopción del ciclo de vida de la escena. Para obtener detalles sobre cómo adoptar el ciclo de vida de UIScene, lee la nota técnica: “Migrating to the UIKit scene-based life cycle”. Dada la importancia de las escenas, te mostraré un ejemplo práctico. Desarrollé una app que rastrea el tiempo que dedico a una tarea específica. Tiene una función que me permite transmitir la tarea actual por AirPlay a un Apple TV. Es responsabilidad de AppDelegate determinar la configuración de la escena para una sesión de conexión. En el método delegado configurationForConnecing SceneSession, verifico el rol de la sesión de escena. Si el rol es una pantalla externa no interactiva, devuelvo una configuración de escena personalizada. De lo contrario, se prefiere la configuración de la escena principal. Cada configuración se define en el archivo Info.plist de la app.

    UISceneDelegate administra el ciclo de vida de una escena individual. En sceneWillConnectToSession, primero creo una ventana y la asocio con la escena de conexión. Ten en cuenta que, si la configuración de tu escena especifica un guion gráfico, la creación de la ventana se produce automáticamente.

    Especifico el rootViewController de la ventana y le proporciono datos específicos de la escena, como timerModel. Para mi app, es importante pausar el temporizador cuando la escena pasa a segundo plano. Para lograr esto, implemento el método delegado sceneDidEnterBackground y pongo en pausa el temporizador. Me encargo de la restauración del estado para garantizar que el estado de la IU de una escena conectada sea exactamente como estaba antes. Mi delegado de escena proporciona una actividad de restauración de estado, que puede incluir selecciones, rutas de navegación y otros estados de la IU. El sistema persiste este estado de IU y lo asocia con la instancia de escena. Si la escena se vuelve a conectar posteriormente, la actividad de restauración del estado se pone a disposición en el método delegado userActivity de restoreInteractionStateWith. Al completar el modelo del temporizador con información de la actividad del usuario, me aseguro de que el estado de la IU de la escena de conexión sea exactamente como estaba antes.

    Al adoptar el ciclo de vida UIScene, tengo bases sólidas para una app flexible. Ahora, analizaré los controladores de vista de contenedor y explicaré cómo son vitales para crear una aplicación flexible. Un controlador de vista de contenedor es responsable de administrar el diseño de uno o más controladores de vista secundarios. UIKit proporciona una serie de controladores de vista de contenedor que están diseñados para ser flexibles. Primero, hablaré de UISplitViewController. UISplitViewController administra la visualización de múltiples columnas adyacentes de contenido, lo que permite una navegación fluida a lo largo de una jerarquía de información. Cuando el espacio horizontal es limitado, el controlador de Split View se adapta contrayendo sus columnas en una pila de navegación. UISplitViewController obtiene una serie de nuevas características, comenzando con el cambio de tamaño de columna interactivo. Ahora puedes cambiar el tamaño de las columnas arrastrando los separadores del controlador de Split View. Con el puntero, su forma se adaptará para indicar las direcciones en las que se puede cambiar el tamaño de una columna. UISplitViewController proporciona un ancho mínimo, máximo y preferido predeterminado para cada columna. Es posible que haya columnas en tu app que prefieran mostrar contenido en anchos mayores o que solo requieran una fracción del ancho predeterminado para seguir siendo funcionales. Puedes personalizar los anchos mínimo, máximo y preferido de cada columna utilizando las propiedades de splitViewController. Ten cuidado de no requerir un ancho que limite la cantidad de columnas que se pueden mostrar, ya que esto reduce la flexibilidad de tu app. Es posible que tu IU deba adaptarse dependiendo de si el controlador de Split View está expandido o contraído. En Mail, los indicadores de divulgación se muestran cuando splitViewController está contraído, para transmitir que se puede revelar contenido adicional al seleccionar una celda. Una nueva característica, el entorno de diseño del controlador de Split View, transmite si un controlador Split View anterior está expandido o contraído. En este ejemplo, se consulta el rasgo para agregar condicionalmente un indicador de divulgación cuando se contrae el controlador de Split View. Otra novedad es el soporte de primera clase para columnas de inspector. Un inspector es una columna dentro de un controlador de Split View que proporciona detalles adicionales del contenido seleccionado. Vista Previa usa un inspector para mostrar metadatos junto a la foto en la columna secundaria. Cuando se expande el controlador de Split View, la columna del inspector se encuentra en el borde posterior, adyacente a la columna secundaria.

    Cuando está contraído, el controlador de Split View se adapta automáticamente y presenta la columna del inspector como una hoja.

    Para incorporar un inspector en tu controlador de Split View, especifica un controlador de vista para la columna del inspector. Cuando aparece por primera vez el controlador de Split View, la columna del inspector está oculta. Llama a show para mostrar la columna del inspector. UISplitViewController está diseñado para ser flexible y garantizará que tu app ofrezca la mejor experiencia de navegación en cualquier tamaño. Otro contenedor a tu disposición es UITabBarController. UITabBarController muestra múltiples paneles de contenido mutuamente excluyentes en la misma área. La barra de pestañas permite cambiar rápidamente entre pestañas, conservando al mismo tiempo el estado actual dentro de cada panel. Además, la apariencia de la barra de pestañas se adapta a cada plataforma.

    En el iPhone, la barra de pestañas se encuentra en la parte inferior de la escena. En la Mac, la barra de pestañas puede residir en la barra de herramientas o mostrarse como una barra lateral.

    En el Apple Vision Pro, la barra de pestañas se muestra en un adorno en el borde anterior de la escena. En el iPad, la barra de pestañas se encuentra en la parte superior de la escena junto a los controles de navegación. La barra de pestañas también se puede adaptar como barra lateral, permitiendo un acceso rápido a colecciones de contenido. Los grupos de pestañas muestran destinos adicionales en la barra lateral. Por ejemplo, en la app Música del iPad, el grupo de pestañas Biblioteca incluye Artistas, Álbumes y más.

    Cuando la barra lateral no está disponible, el grupo Biblioteca es un destino de pestaña.

    UITabBarController ofrece una API para gestionar sin problemas esta adaptación. En primer lugar, proporciona al grupo de pestañas un controlador de navegación administrativo. Cuando se selecciona una pestaña de hoja del grupo de pestañas, su controlador de vista, junto con los controladores de vista de sus grupos antecesores, se insertan en esta pila de navegación. Para personalizar los controladores de vista enviados a esta pila de navegación, implementa el método delegado UITabBarController, pestaña displayedViewControllersFor. En este ejemplo, cuando no se puede seleccionar la pestaña Biblioteca, el método delegado devuelve una matriz vacía para omitir el controlador de vista de la pestaña Biblioteca de la pila.

    Para obtener más información sobre cómo UITabBarController ofrece flexibilidad para mostrar una barra de pestañas o una barra lateral, mira “Elevate your tab and sidebar experience in iPadOS” de la WWDC24. Adoptar controladores de vista de contenedor, como UISplitViewController y UITabBarController, es la mejor manera de garantizar que tu app sea flexible. Si bien estos contenedores están diseñados para admitir una amplia gama de tamaños, tu app puede requerir un tamaño mínimo para mantener la funcionalidad principal. Puedes utilizar la API UISceneSizeRestrictions para expresar el tamaño mínimo preferido del contenido de tu escena. El mejor momento para especificar el tamaño mínimo es cuando la escena está a punto de conectarse. En este ejemplo, especifico un ancho mínimo preferido de 500 puntos. Para que tu app sea verdaderamente flexible, tu propia IU debe poder adaptarse. A continuación, hablaré sobre las API que te ayudarán a crear una IU adaptativa. Un paso crucial para hacer que tu IU sea adaptable es garantizar que el contenido permanezca dentro del área segura. El área segura es una región dentro de una vista que es apropiada para contenido interactivo o importante. El contenido ubicado fuera de esta región es vulnerable a quedar cubierto, por ejemplo, por una barra de navegación o una barra de herramientas.

    El contenido también podría verse ocultado por la IU del sistema, como la barra de estado, o incluso por funciones del dispositivo, como Dynamic Island.

    La barra lateral agrega una inserción de área segura no simétrica a la columna adyacente en un controlador de Split View. El fondo puede extenderse libremente fuera del área segura, debajo de la barra lateral.

    El contenido, como la transcripción del mensaje, se coloca dentro del área segura para garantizar que permanezca visible. Las burbujas de mensajes se insertan desde los bordes del área segura utilizando márgenes de diseño. Esto proporciona un espaciado consistente y una separación visual clara de la barra lateral.

    Cada vista proporciona guías de diseño para aplicar márgenes estándar alrededor del contenido. Los márgenes de diseño se insertan desde el área segura de manera predeterminada. En este ejemplo, solicito una guía de diseño para posicionar el contenido dentro de la vista del contenedor. Luego, uso esta guía de diseño para configurar restricciones para la vista de contenido.

    En iPadOS 26, las escenas obtienen un nuevo control para cerrar, minimizar y organizar la ventana, similar a macOS. El control de ventana aparece junto al contenido de la escena.

    Una escena puede especificar un estilo de control de ventanas preferido para complementar su contenido. Para especificar una preferencia, implementa el método UIWindowSceneDelegate preferredWindowingControlStyle para la escena.

    Los componentes del sistema, como UINavigationBar, se adaptan automáticamente organizando sus subvistas alrededor del control de ventana. Tu IU también debe adaptarse al control de ventana, independientemente de su estilo.

    Para garantizar que tu IU no quede obstruida, utiliza una guía de diseño que tenga en cuenta el control de la ventana. En este ejemplo, solicito una guía de márgenes de diseño con adaptación de esquinas horizontales. Esta guía de diseño es ideal para contenido tipo barra en la parte superior de una escena, que debe insertarse desde el borde posterior del control de la ventana. Luego, uso esta guía de diseño para configurar restricciones para la vista de contenido. Cuando tu IU es adaptativa, la orientación de la interfaz debe ser redundante. El cambio de tamaño de la escena, la rotación del dispositivo y los cambios en el diseño de la ventana, en última instancia, dan como resultado una modificación en el tamaño de la escena. Algunas categorías de apps pueden beneficiarse del bloqueo temporal de la orientación. Por ejemplo, un juego de conducción puede querer bloquear la orientación cuando se espera que el dispositivo gire para dirigir un vehículo.

    Cuando un controlador de vista está visible, puede preferir una orientación de interfaz bloqueada. Para especificar una preferencia, anula prefersInterfaceOrientationLocked en la subclase de tu controlador de vista. Siempre que esta preferencia cambie, llama a setNeedsUpdateOfPrefersInterfaceOrientationLocked.

    Para observar el bloqueo de la orientación de la interfaz, implementa el método UIWindowSceneDelegate, didUpdateEffectiveGeometry. Luego, compara si el valor de isInterfaceOrientationLocked cambió. Para que tu app sea verdaderamente adaptable, debe responder rápidamente al cambio de tamaño. Es posible que haya elementos de la IU de tu app que requieran un alto costo computacional para utilizarlas.

    Esto es común en los juegos, donde puede ser necesario redimensionar una serie de recursos cuando la escena cambia de tamaño. No es necesario volver a representar los recursos para cada tamaño dentro de una interacción de cambio de tamaño. En este ejemplo, se consulta isInteractivelyResizing para actualizar los recursos para un nuevo tamaño de escena solo después de que finalice la interacción.

    Las apps flexibles permiten a las personas utilizar sus dispositivos como quieran. Ofrecen excelentes experiencias en una amplia gama de tamaños, lo que permite utilizarlos en cualquier orientación o diseño. La clave UIRequiresFullscreen Info.plist es un modo de compatibilidad de iOS 9 que evita el cambio de tamaño de la escena. UIRequiresFullscreen está obsoleto y se ignorará en una versión futura. Las apps adaptables no necesitan esta clave y deberían eliminarla.

    Existe otro modo de compatibilidad, específicamente para hardware nuevo. Antes, cuando se lanzaba nuevo hardware con un tamaño de pantalla diferente, el sistema escalaba o agregaba formato adaptado a la IU de la app. Esa escala se mantendrá vigente hasta que crees un SDK más nuevo y vuelvas a enviar tu app. Una vez que compiles y envíes con el SDK de iOS 26, el sistema ya no escalará ni colocará letras en la IU de tu app para un nuevo tamaño de pantalla.

    Estas son las mejores prácticas para garantizar que tu app sea flexible. ¿Qué sigue? Adopta el ciclo de vida de la escena en tu app para asegurar bases sólidas para una app flexible. Utiliza controladores de vista de contenedor para administrar componentes de tu IU. Por último, aprovecha las API como guías de diseño para crear una IU adaptable. No puedo esperar a ver que tus apps se vuelvan más flexibles. ¡Gracias!

    • 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 - Introducción
    • Haz que las apps UIKit sean flexibles y adaptables a diferentes tamaños de pantalla y plataformas al utilizar escenas, controladores de vista de contenedor y otras API.

    • 0:58 - Escenas
    • Las escenas representan instancias distintas de la interfaz de usuario de una app. Cada escena administra su estado de forma independiente y se restaura sin problemas al volver a conectarse. Las escenas proporcionan contexto sobre la visualización de la app, tales como el tamaño de la pantalla y la geometría de la ventana. A partir del próximo lanzamiento importante posterior a iOS 26, la adopción del ciclo de vida UIScene será obligatoria.

    • 4:58 - Controladores de vista de contenedor
    • Los controladores de vista de contenedor como 'UISplitViewController' y 'UITabBarController' administran el diseño de uno o más controladores de vista secundarios. Estos ayudan a que las apps sean flexibles, adaptables y personalizables. Utiliza la API UISceneRestrictions para expresar el tamaño mínimo de las escenas en la app.

    • 10:45 - Adaptabilidad
    • Las guías de diseño y los márgenes ayudan a posicionar el contenido de una app de manera consistente dentro del área segura del dispositivo. iPadOS 26 introduce un nuevo control de ventana. Las apps pueden especificar 'preferredWindowingControlStyle' y guías de diseño para acomodar estos controles. Las interfaces de usuario adaptables deben responder rápidamente a los cambios de tamaño y orientación, pero algunas apps pueden querer anular 'prefersInterfaceOrientationLocked' para bloquear temporalmente la orientación. Para operaciones computacionalmente costosas, marca 'isInteractivelyResizing' para realizar las operaciones después de que finalice una interacción. 'UIRequiresFullscreen' está obsoleto.

    • 15:39 - Compatibilidad futura
    • Con el SDK de iOS 26, las apps se adaptan automáticamente a nuevos tamaños de pantalla sin necesidad de actualizaciones manuales ni reenvíos.

    • 16:07 - Próximos pasos
    • Para crear una app flexible, adopta el ciclo de vida de la escena, utiliza controladores de vista de contenedor y aprovecha las API como guías de diseño.

Developer Footer

  • Videos
  • WWDC25
  • Haz que tu app UIKit sea más flexible
  • 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