Francisco José García Navarro
Publicado:WWDC 2026 para equipos en producción: Swift 6.3, SwiftUI y lo que rompe en iOS 27
" La IA se ha comido los titulares. Pero si mantienes una app grande en producción, el trabajo real de este ciclo está en Swift 6.3/6.4, en el nuevo SwiftUI y en los cambios de plataforma que rompen. Esto es lo que planificaría antes de septiembre. "
Cierro con este artículo mi serie sobre WWDC 2026. Ya he escrito sobre la IA en iOS: Xcode agéntico y Foundation Models y sobre por qué la accesibilidad de iOS 27 no te pone en regla con la EAA. Si buscas eso, está ahí.
Este artículo va de lo otro. De lo que no sale en los titulares pero determina cuánto va a dolerte el ciclo iOS 27: los cambios de plataforma que rompen, lo que traen Swift 6.3 y 6.4, y un SwiftUI que este año ha ido a los cimientos en lugar de a los fuegos artificiales.
Después de 11 años haciendo iOS nativo en apps de banca, retail y seguros, tengo una regla: los ciclos de WWDC "aburridos" son los que más trabajo dan. Este es uno de ellos.
Lo que rompe: los cambios que no puedes posponer
1. El ciclo de vida UIScene pasa a ser obligatorio. Confirmado sin ambigüedad en la sesión "Modernize your UIKit app": al compilar con el SDK de iOS 27, el ciclo de vida basado en UIApplicationDelegate deja de ser una opción — sin UISceneDelegate, tu app directamente no arranca. Si llevas años arrastrando la migración a escenas — y he visto muchas apps que la arrastran — este es el momento en que deja de ser deuda técnica y pasa a ser bloqueante.
2. Tu app de iPhone pasa a ser totalmente redimensionable. En iOS 27, una app de iPhone corriendo en iPad se redimensiona como cualquier app de iPad, y en iPhone Mirroring la ventana se estira libremente en el Mac. Se acabó el modo compatibilidad de tamaño fijo. Y hay dos derribos conceptuales que vienen con ello: el idiom deja de servir para decisiones de layout (una app iPhone en iPad sigue reportando idiom phone, pero es redimensionable) y la orientación de interfaz también — en entornos redimensionables, tus orientaciones soportadas pasan a ser una preferencia que el sistema puede ignorar. Lo que queda en pie: size classes, el tamaño real de tu vista y la geometría efectiva de la window scene. Nada de UIScreen.main. Para juegos, UIRequiresFullscreen sigue honrándose en iPhone, pero cambia de significado: ya no te saca del redimensionado, sino que lo convierte en redimensionado discreto por configuraciones de pantalla. Xcode 27 trae el Device Hub y Previews con redimensionado en vivo precisamente para probar todo esto.
3. En gestión de dispositivos, el declarativo ya es el estándar. El mensaje de Apple en la sesión de device management es explícito: la gestión declarativa "ya no es el futuro, es el estándar", con las configuration profiles de credenciales en transición a configuraciones declarativas. Si distribuyes a flotas corporativas con un MDM anclado en el modelo clásico de comandos, la dirección es inequívoca y conviene hablar con tu equipo de IT este verano — no cuando el vendor de MDM te fuerce el cambio.
De los tres, el que más subestiman los equipos es el segundo. Redimensionable no es "que no crashee al cambiar de tamaño": es que tus layouts, tus caches de imágenes, tus celdas custom y tus supuestos sobre UIScreen aguanten geometría variable. En una app con años de historia, eso es una auditoría, no un ticket. Apple lo sabe, y por eso Xcode 27 incluye una app modernization skill para agentes que convierte automáticamente llamadas a UIScreen.main, checks de orientación e incluso la migración a scene lifecycle — de lo que significa delegar ese trabajo en un agente (y auditar lo que produce) hablé en el artículo de IA de esta serie.
Swift 6.3 y 6.4: menos fricción, más control
Lo primero que hay que decir: si tu migración a concurrencia estricta se atascó en 2024 o 2025, Swift 6.3/6.4 no la hace por ti — pero sí elimina varias de las piedras concretas con las que tropezaban los equipos que he visto migrar. El cambio grande de modelo (MainActor por defecto, la "Approachable Concurrency") llegó con Swift 6.2; lo de este año es limar fricción.
Concurrencia: las piedras pequeñas que paraban migraciones
weak let. El clásico: una clase que necesitaba@unchecked Sendablesolo porque tenía unweak var. Ahora eseweakpuede serlet, inmutable, y el checking de Sendable pasa limpio. Es un cambio de una línea que elimina un@unchecked— y cada@uncheckedque eliminas es una promesa menos que mantener a mano.~Sendableexplícito. Puedes declarar que un tipo no es Sendable, y además sin bloquear que sus subclases sí lo sean. En jerarquías de UIKit heredadas, esto documenta la intención en el sitio correcto: el código.- Aviso por errores silenciados en Tasks. Si lanzas un
Taskcuyo error nadie recoge, el compilador ahora te avisa. En código de producción he auditado demasiadosTask { try await ... }donde el error moría en silencio. Este warning solo ya justifica actualizar. asyncendefer. Desaparece la restricción de llamar funciones async desde un bloquedefer. Limpieza de recursos asíncrona sin contorsiones.
@diagnose: control quirúrgico de warnings
Esta es la que más me interesa para trabajo enterprise. @diagnose permite cambiar el comportamiento de grupos de warnings en una declaración concreta:
@diagnose(.ignore, .deprecatedDeclaration)
func legacyBridge() {
// API deprecada que aún no podemos sustituir:
// silenciada aquí, y solo aquí
}
@diagnose(.error, .strictMemorySafety)
func verifySignature(_ data: Span<UInt8>) {
// en código crítico de seguridad, lo que era warning ahora es error
}
En una migración por módulos, esto cambia la conversación con el equipo: en lugar de un mar de warnings que todo el mundo aprende a ignorar (y con ellos, los warnings que sí importan), acotas el ruido a los puntos donde la deuda es consciente y elevas a error lo que no quieres que se cuele. En apps de banca, poder forzar strict memory safety como error en las funciones de criptografía y firma es exactamente el tipo de herramienta que quiero.
Module selectors: :: para desambiguar módulos
Swift 6.3 estrena sintaxis para el conflicto clásico de las apps modularizadas: dos módulos con tipos del mismo nombre.
import SwiftUI
import MiDatabase // también define un tipo View
let vista: SwiftUI::View // "::" fuerza que SwiftUI se interprete como módulo
Si trabajas en una app de 100+ módulos, sabes que esto no es un caso de laboratorio: pasa, y hasta ahora se resolvía con typealias defensivos o renombrados incómodos. Ojo al consejo de la propia Apple, que suscribo: es una herramienta para resolver conflictos que no controlas, no una licencia para diseñar APIs con nombres duplicados.
Swift Testing: la migración desde XCTest ya no da miedo
Para equipos enterprise con suites grandes, lo de este año es importante: los fallos de aserción de XCTest ahora se reportan como issues cuando se llaman desde Swift Testing, y viceversa — #expect funciona dentro de un XCTestCase. Traducción: puedes migrar tu suite por partes, mantener tus helpers construidos sobre XCTest, y no perder cobertura por el camino. Además llegan severidad configurable en Issue.record (issues que avisan sin romper la CI), Test.cancel para cancelar dinámicamente argumentos de tests parametrizados, y swift test con reintentos configurables para cazar tests flaky re-ejecutando solo los que fallan.
Si llevas un año diciendo "migraremos a Swift Testing cuando sea seguro": ya es seguro.
Rendimiento: ownership sin punteros unsafe
Swift 6.3/6.4 sigue construyendo el sistema de ownership, y por primera vez lo veo lo bastante completo para código de producción sensible al rendimiento:
- Accessors
borrowymutate: acceso a storage compartido sin copiar. El ejemplo canónico: un struct con unInlineArrayde 2 KB dentro — conget/setcopias los 2 KB para tocar un Int; conborrow/mutate, mutas in situ. @inline(always)y@specialized: control explícito sobre inlining y especialización de genéricos cuando el optimizador no acierta solo.Ref/MutableRef: mantener "abierto" un acceso (por ejemplo, un lookup de diccionario dentro de un bucle) de forma segura, sin el truco del parámetroinout.- Protocolo
Iterable: buclesforque toman prestados los elementos en lugar de copiarlos, sin reference counting por iteración.
¿Necesitas esto en tu ViewModel? No. ¿Lo necesitas en un framework de cifrado, un parser de mercado en tiempo real o un pipeline de imagen? Ahí es donde antes acababas en UnsafePointer — y ahora no.
Y una nota estratégica: Swift oficial en Android
Swift 6.3 incluye el primer SDK oficial de Swift para Android, con interoperabilidad Java/Kotlin mejorada. No cambia nada hoy para una app iOS en producción, pero sí cambia una conversación que tengo a menudo con CTOs: la de "necesitamos compartir lógica entre plataformas". Hasta ahora la respuesta pragmática era KMP para la capa de dominio; a partir de ahora, compartir Swift es una opción que hay que evaluar en serio. Lo dejo apuntado — da para un artículo propio.
SwiftUI: el año de los cimientos
Lo llamativo de SwiftUI este año no es ninguna API espectacular. Es que casi todo lo importante mejora sin tocar código — y las dos o tres cosas que sí tocas van directas a dolores enterprise.
Liquid Glass v2, gratis. Recompilas con el SDK nuevo y la app adopta el aspecto refinado: esquinas consistentes en macOS, respuesta al slider de tinte del sistema, atenuación de ventanas inactivas en iPad. Cero líneas.
Toolbars pensadas para redimensionar. Con las apps ahora redimensionables, el sistema oculta items de toolbar cuando no caben. Las APIs nuevas te dan el control que faltaba: visibilityPriority(.high) para que Deshacer/Rehacer no desaparezcan, ToolbarOverflowMenu para agrupar lo secundario, placements fijados para lo que nunca debe ocultarse, y toolbarMinimizeBehavior(.onScrollDown) para recuperar espacio vertical. Si tienes una app de productividad, esta es la primera API que tocaría.
@State ahora es una macro — y es lazy. El cambio silencioso con más impacto en rendimiento: las clases @Observable almacenadas en @State se inicializan una sola vez, no en cada reinicialización de la vista. Hasta ahora, cada re-init del padre creaba una instancia nueva de tu store... que se tiraba a la basura inmediatamente. Si tus stores hacen trabajo en el init (y no deberían, pero el mundo real es el mundo real), esto elimina trabajo desperdiciado en cada update. Aviso: es la conversión de State de Dynamic Property a macro, y puede romper código — si asignas un valor por defecto y además asignas en el init, tendrás un error de "use before initialization". Se arregla quitando el default redundante. Y se ha retroportado hasta iOS 17.
Type-checking más rápido con ContentBuilder. Los builders más comunes (Section, Group, ForEach...) se unifican bajo un único ContentBuilder, eliminando la explosión combinatoria de overloads que producía el famoso "unable to type-check this expression in reasonable time". Funciona con cualquier deployment target al compilar con Xcode 27. En codebases SwiftUI grandes, esto es tiempo de compilación real que recuperas.
AsyncImage por fin cachea. Caché HTTP estándar por defecto, respetando cabeceras del servidor, sin cambios de código. Y si necesitas control, puedes pasar tu propio URLRequest o una URLSession con la URLCache que quieras. La cantidad de wrappers caseros de AsyncImage que he visto en auditorías solo para tener caché... jubiladlos.
Observation Tracking en UIKit y AppKit, activado por defecto. Para las apps que aún viven mayoritariamente en UIKit — que son la mayoría de las enterprise — este es el cambio más útil del año: las vistas UIKit/AppKit ahora observan automáticamente propiedades de tipos @Observable dentro de draw, layout, updateConstraints y compañía. Se acabó el setNeedsDisplay() manual para sincronizar vistas con el modelo. Activo por defecto en las releases de 2026, y retroportable hasta iOS 18 / macOS 15 con una clave de Info.plist. La jugada estratégica: migra tu modelo a @Observable antes de tocar una sola vista — tus UIView existentes ya se benefician, y cuando reescribas un componente en SwiftUI, el modelo ya estará listo. Es el patrón Strangler Fig aplicado a la capa de datos.
Reordenación y swipe actions en cualquier contenedor. El nuevo API reorderable + reorderContainer da drag-to-reorder en List, LazyVGrid o cualquier contenedor con el mismo código, y las swipe actions dejan de ser exclusivas de List. Menos motivos para volver a UICollectionView por una interacción.
Y para apps de documentos, hay una API nueva completa (ReadableDocument/WritableDocument) con lectura/escritura asíncrona fuera del main actor y escritura incremental comparando snapshots. Nicho, pero si es tu nicho, es el rework que llevabas años pidiendo.
Qué haría yo antes de septiembre
Si llevo la planificación técnica de una app grande, mi orden es este:
- Auditar los tres cambios que rompen. ¿Estamos en UIScene? ¿Aguantamos redimensionado? ¿Dependemos del MDM clásico? Cada "no" es un epic, no un ticket.
- Compilar con Xcode 27 beta ya, aunque no se publique con él. El coste de descubrir en agosto lo que podías saber en julio lo pagas en septiembre.
- Probar la app en el simulador redimensionable. Es la forma más barata de descubrir supuestos rotos de geometría.
- Retomar la migración de concurrencia si está parada, usando
@diagnosepara acotar el ruido yweak let/~Sendablepara limpiar los@unchecked Sendableacumulados. - Planificar la migración a Swift Testing por módulos, ahora que la interoperabilidad con XCTest garantiza no perder cobertura.
- Revisar el error de compilación del
@Statemacro en cuanto compiles con el SDK nuevo: es mecánico de arreglar, pero hay que pasarlo.
WWDC 2026 es un ciclo de arremangarse: poca pirotecnia y bastante fontanería. Pero la fontanería bien hecha es lo que separa una app que envejece con dignidad de una que se llena de parches. Y a diferencia de la IA — donde todavía hay margen para esperar y ver — aquí los deadlines los pone el SDK.
Preguntas frecuentes
¿Qué cambios de iOS 27 pueden romper una app existente?
Tres: el ciclo de vida UIScene pasa a ser obligatorio al compilar con el SDK de iOS 27 (sin UISceneDelegate la app no arranca), las apps de iPhone pasan a ser totalmente redimensionables en iPad y en iPhone Mirroring, y la gestión de dispositivos declarativa se convierte en el estándar frente al modelo clásico de comandos MDM.
¿Swift 6.3 facilita la migración a concurrencia estricta?
No la hace por ti, pero elimina fricciones concretas: weak let permite limpiar muchos @unchecked Sendable, ~Sendable documenta tipos no-Sendable de forma explícita, y el compilador avisa de errores silenciados en Tasks. El cambio de modelo grande llegó con Swift 6.2; 6.3/6.4 liman las piedras que paraban migraciones.
¿Es seguro migrar de XCTest a Swift Testing en 2026?
Sí. Desde este ciclo, los fallos de aserción de XCTest se reportan como issues al llamarse desde Swift Testing y viceversa, lo que permite migrar la suite por módulos manteniendo los helpers existentes sin perder cobertura.
¿Qué mejoras de SwiftUI llegan sin cambiar código?
Liquid Glass v2 al recompilar con el SDK nuevo, caché HTTP por defecto en AsyncImage, type-checking más rápido con ContentBuilder y Observation Tracking automático en UIKit/AppKit (activado por defecto en las releases de 2026).
Fuentes (sesiones WWDC 2026)
¿Tu equipo tiene por delante la adopción del SDK de iOS 27, la migración a concurrencia estricta o una app UIKit que necesita modernizarse sin parar el roadmap? Es exactamente el tipo de trabajo que hago como contractor iOS senior integrado en equipos.
Sobre el autor
Francisco José García Navarro es cofundador y Arquitecto iOS Senior de AtalayaSoft, con más de 25 años en desarrollo de software y 11+ en iOS nativo. A lo largo de su carrera ha trabajado con clientes de alto perfil como Zara (Inditex), Banco Santander, AXA, El País, National Geographic, Fox International Channels y el Museo Thyssen-Bornemisza.