-
Novedades de UIKit
Moderniza tu app con las últimas API en UIKit, que incluyen soporte mejorado para la barra de menú, seguimiento automático de observaciones, un nuevo método de actualización de UI y mejoras en las animaciones. También mencionaremos cómo puedes incluir escenas SwiftUI en tu app UIKit y explorar símbolos SF, selectores de color HDR y más.
Capítulos
- 0:00 - Introducción
- 0:59 - Nuevo sistema de diseño
- 2:29 - Contenedores y adaptabilidad
- 3:21 - La barra de menú
- 9:58 - Mejoras arquitectónicas
- 10:21 - Seguimiento automático de observaciones
- 12:33 - Nuevo método de actualización de la IU
- 15:45 - Mejoras en las animaciones
- 17:45 - Actualizaciones de escenas
- 18:55 - Compatibilidad con colores HDR
- 20:38 - Notificaciones Swift
- 21:20 - Migrar a un ciclo de vida basado en escenas
- 22:40 - Compatibilidad de OpenURL con URL de archivos
- 23:17 - SF Symbols 7
- 25:13 - Próximos pasos
Recursos
Videos relacionados
WWDC25
- Conoce el nuevo sistema de diseño
- Crea una app de UIKit con el nuevo diseño
- Haz que tu app UIKit sea más flexible
- Mejora el diseño de tu app para iPad
- Novedades de SF Symbols 7
WWDC24
WWDC23
WWDC21
-
Buscar este video…
-
-
4:56 - Main menu system configuration
// Main menu system configuration var config = UIMainMenuSystem.Configuration() // Declare support for default commands, like printing config.printingPreference = .included // Opt out of default commands, like inspector config.inspectorPreference = .removed // Configure the Find commands to be a single "Search" element config.findingConfiguration.style = .search -
5:39 - Main menu system build configuration
// Main menu system configuration // Have the main menu system build using this configuration, and make custom additions. // Call this early, e.g. in application(_:didFinishLaunchingWithOptions:), and call it once UIMainMenuSystem.shared.setBuildConfiguration(config) { builder in builder.insertElements([...], afterCommand: #selector(copy(_:))) let deleteKeyCommand = UIKeyCommand(...) builder.replace(command: #selector(delete(_:)), withElements: [deleteKeyCommand]) } -
7:01 - Keyboard shortcut repeatability
// Keyboard shortcut repeatability let keyCommand = UIKeyCommand(...) keyCommand.repeatBehavior = .nonRepeatable -
7:43 - Focus-based deferred menu elements (App Delegate)
// Focus-based deferred menu elements extension UIDeferredMenuElement.Identifier { static let browserHistory: Self = .init(rawValue: "com.example.deferred-element.history") } // Create a focus-based deferred element that will display browser history let historyDeferredElement = UIDeferredMenuElement.usingFocus( identifier: .browserHistory, shouldCacheItems: false ) // Insert it into the app’s custom History menu when building the main menu builder.insertElements([historyDeferredElement], atEndOfMenu: .history) -
8:06 - Focus-based deferred menu elements (View Controller)
// Focus-based deferred menu elements class BrowserViewController: UIViewController { // ... override func provider( for deferredElement: UIDeferredMenuElement ) -> UIDeferredMenuElement.Provider? { if deferredElement.identifier == .browserHistory { return UIDeferredMenuElement.Provider { completion in let browserHistoryMenuElements = profile.browserHistoryElements() completion(browserHistoryMenuElements) } } return nil } } -
10:54 - Using an Observable object and automatic observation tracking
// Using an Observable object and automatic observation tracking @Observable class UnreadMessagesModel { var showStatus: Bool var statusText: String } class MessageListViewController: UIViewController { var unreadMessagesModel: UnreadMessagesModel var statusLabel: UILabel override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() statusLabel.alpha = unreadMessagesModel.showStatus ? 1.0 : 0.0 statusLabel.text = unreadMessagesModel.statusText } } -
11:48 - Configuring a UICollectionView cell with automatic observation tracking
// Configuring a UICollectionView cell with automatic observation tracking @Observable class ListItemModel { var icon: UIImage var title: String var subtitle: String } func collectionView( _ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath ) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) let listItemModel = listItemModel(for: indexPath) cell.configurationUpdateHandler = { cell, state in var content = UIListContentConfiguration.subtitleCell() content.image = listItemModel.icon content.text = listItemModel.title content.secondaryText = listItemModel.subtitle cell.contentConfiguration = content } return cell } -
13:27 - Using automatic observation tracking and updateProperties()
// Using automatic observation tracking and updateProperties() @Observable class BadgeModel { var badgeCount: Int? } class MyViewController: UIViewController { var model: BadgeModel let folderButton: UIBarButtonItem override func updateProperties() { super.updateProperties() if let badgeCount = model.badgeCount { folderButton.badge = .count(badgeCount) } else { folderButton.badge = nil } } } -
16:57 - Using the flushUpdates animation option to automatically animate updates
// Using the flushUpdates animation option to automatically animate updates // Automatically animate changes with Observable objects UIView.animate(options: .flushUpdates) { model.badgeColor = .red } -
17:23 - Automatically animate changes to Auto Layout constraints with flushUpdates
// Automatically animate changes to Auto Layout constraints UIView.animate(options: .flushUpdates) { // Change the constant of a NSLayoutConstraint topSpacingConstraint.constant = 20 // Change which constraints are active leadingEdgeConstraint.isActive = false trailingEdgeConstraint.isActive = true } -
18:07 - Setting up a UIHostingSceneDelegate
// Setting up a UIHostingSceneDelegate import UIKit import SwiftUI class ZenGardenSceneDelegate: UIResponder, UIHostingSceneDelegate { static var rootScene: some Scene { WindowGroup(id: "zengarden") { ZenGardenView() } #if os(visionOS) ImmersiveSpace(id: "zengardenspace") { ZenGardenSpace() } .immersionStyle(selection: .constant(.full), in: .mixed, .progressive, .full) #endif } } -
18:28 - Using a UIHostingSceneDelegate
// Using a UIHostingSceneDelegate func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { let configuration = UISceneConfiguration(name: "Zen Garden Scene", sessionRole: connectingSceneSession.role) configuration.delegateClass = ZenGardenSceneDelegate.self return configuration } -
18:41 - Requesting a scene
// Requesting a scene func openZenGardenSpace() { let request = UISceneSessionActivationRequest( hostingDelegateClass: ZenGardenSceneDelegate.self, id: “zengardenspace")! UIApplication.shared.activateSceneSession(for: request) } -
19:18 - HDR color support
// Create an HDR red relative to a 2.5x peak white let hdrRed = UIColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0, linearExposure: 2.5) -
19:50 - HDR color picking
// Support picking HDR colors relative to a // maximum peak white of 2x colorPickerController.maximumLinearExposure = 2.0 -
20:06 - Mixing SDR and HDR content
// Mixing SDR and HDR content registerForTraitChanges([UITraitHDRHeadroomUsageLimit.self]) { traitEnvironment, previousTraitCollection in let currentHeadroomLimit = traitEnvironment.traitCollection.hdrHeadroomUsageLimit // Update HDR usage based on currentHeadroomLimit’s value } -
20:54 - Adopting Swift notifications
// Adopting Swift notifications override func viewDidLoad() { super.viewDidLoad() let keyboardObserver = NotificationCenter.default.addObserver( of: UIScreen.self for: .keyboardWillShow ) { message in UIView.animate( withDuration: message.animationDuration, delay: 0, options: .flushUpdates ) { // Use message.endFrame to animate the layout of views with the keyboard let keyboardOverlap = view.bounds.maxY - message.endFrame.minY bottomConstraint.constant = keyboardOverlap } } } -
24:26 - Using a symbol content transition to automatically animate symbol updates
// Using a symbol content transition to automatically animate symbol updates var configuration = UIButton.Configuration.plain() configuration.symbolContentTransition = UISymbolContentTransition(.replace)
-
-
- 0:00 - Introducción
Obtén información sobre las mejoras de UIKit en iOS, iPadOS, tvOS, visionOS y Mac Catalyst. Este video abarca el nuevo sistema de diseño, contenedores y adaptabilidad, API para la barra de menús en iPadOS y Mac Catalyst, avances arquitectónicos centrales y mejoras generales de las estructuras.
- 0:59 - Nuevo sistema de diseño
El nuevo sistema de diseño incluye Liquid Glass: un material translúcido y dinámico que renueva los componentes estándares de UIKit y mejora las transiciones de navegación. UIKit también tiene una nueva API para incorporar Liquid Glass en su interfaz de usuario personalizada.
- 2:29 - Contenedores y adaptabilidad
iOS 26 mejora “UISplitViewController” con inspectores para una visualización detallada del contenido y un ajuste dinámico del tamaño de las columnas.
- 3:21 - La barra de menú
iOS 26 mejora la barra de menús del iPad, a la que ahora se puede acceder deslizando el dedo desde la parte superior de la pantalla, para brindar un acceso rápido a las funciones de la app sin un teclado físico. La barra de menús siempre debe mostrar todos los comandos de la app, incluso aquellos que están deshabilitados o no tienen atajos de teclado. Personaliza la barra de menús con la nueva API para la configuración del menú principal e implementa menús dinámicos basados en la vista enfocada. Se incorporan acciones estándares como “Cerrar” y “Nuevo a partir del Portapapeles”. Las acciones para alinear el texto y mostrar u ocultar la barra lateral y el inspector ahora también se muestran para su personalización. Asegúrate de que las acciones estén disponibles en tu app sin depender de la barra de menús.
- 9:58 - Mejoras arquitectónicas
UIKit sigue evolucionando con nuevas funciones para patrones modernos, prácticas recomendadas y una mayor interoperabilidad con SwiftUI.
- 10:21 - Seguimiento automático de observaciones
UIKit ahora hace un seguimiento automático de los objetos Observable a los que se hace referencia en métodos de actualización como “layoutSubviews”, lo que elimina la necesidad de llamar manualmente a “setNeedsLayout”. Esta función está habilitada de forma predeterminada en iOS 26 y puede implementarse en iOS 18 con la clave “UIObservationTrackingEnabled” del archivo Info.plist. Los cambios en las propiedades del modelo Observable que actualizan elementos de la interfaz de usuario activan automáticamente la invalidación de la vista y la reejecución de los métodos de actualización relevantes, lo que mantiene la interfaz sincronizada sin código adicional.
- 12:33 - Nuevo método de actualización de la IU
UIKit introduce un nuevo método, “updateProperties”, disponible en “UIView” y “UIViewController”. Este método se ejecuta de forma independiente antes de “layoutSubviews” y te permite completar contenido, aplicar estilos y configurar comportamientos de manera más eficiente. “updateProperties” hace un seguimiento automático de los objetos Observable y, en caso contrario, se puede activar manualmente llamando a “setNeedsUpdateProperties”. Este método permite evitar pasos de diseño innecesarios, lo que mejora el rendimiento de tu app.
- 15:45 - Mejoras en las animaciones
En iOS 26, UIKit introduce “flushUpdates”, una opción de animación que aplica automáticamente las actualizaciones pendientes antes y después de las animaciones, lo que elimina la necesidad de llamar manualmente a “layoutIfNeeded”. Esto simplifica el código, reduce los errores y funciona con objetos Observable y cambios automáticos en las restricciones de diseño.
- 17:45 - Actualizaciones de escenas
Ahora puedes integrar escenas de SwiftUI en apps de UIKit con el nuevo protocolo “UIHostingSceneDelegate”. Crea apps que se adapten a diferentes dispositivos (como una app de meditación con un jardín zen 2D en iPhone y iPad y una experiencia inmersiva en visionOS) solicitando programáticamente una escena de SwiftUI específica.
- 18:55 - Compatibilidad con colores HDR
En iOS 26, UIKit también mejora el renderizado HDR más allá de las imágenes para incluir colores. Crea colores HDR con “UIColor” y permite seleccionarlos en los selectores de color. Utiliza la nueva función “UITraitHDRHeadroomUsage” para identificar cuándo corresponde una transición de HDR a SDR.
- 20:38 - Notificaciones Swift
En iOS 26, UIKit representa cada notificación como un tipo “NotificationCenter.Message” exclusivo, lo que proporciona notificaciones estrictamente tipificadas para facilitar el manejo de eventos, tal como se muestra en un ejemplo de ajuste del diseño cuando aparece el teclado.
- 21:20 - Migrar a un ciclo de vida basado en escenas
“UIScene” reemplaza “UIApplication” como estándar para el desarrollo de apps, lo que hace que las apps sean más portátiles y flexibles. Debes adoptar el ciclo de vida “UIScene” porque los métodos heredados están obsoletos. Además, a partir de la versión posterior a iOS 26, las apps que no hayan adoptado el ciclo de vida de escena no se iniciarán.
- 22:40 - Compatibilidad de OpenURL con URL de archivos
El método “openURL” ahora permite que las apps transfieran documentos no nativos a visores predeterminados o utilicen controladores de vista previa rápida si no existe un visor predeterminado.
- 23:17 - SF Symbols 7
SF Symbols 7 presenta nuevas capacidades de dibujo, incluidos los efectos “Draw Off” y “Draw On”, el modo de dibujo variable para representar valores arbitrarios a lo largo de una ruta y animaciones de dibujo especiales con transiciones de reemplazo mágico. UIKit ahora ofrece una API para facilitar la adopción de estas transiciones en “UIButton”, y los símbolos se pueden colorear con rellenos en degradé generados automáticamente.
- 25:13 - Próximos pasos
Para actualizar tu app para iOS 26, compílala con el nuevo SDK, ajusta los elementos de interfaz de usuario al nuevo diseño, utiliza contenedores estándares y las nuevas API de menú, y adopta el método “updateProperties” junto con el seguimiento de observaciones para mejorar el rendimiento.