Concurrencia estricta de Swift 6 sin dolor
Swift 6 detecta condiciones de carrera en compilación. Qué significa la concurrencia estricta, los errores típicos que verás y cómo resolverlos con calma.
La gran promesa de Swift 6 es enorme: que sea imposible compilar código con condiciones de carrera. Es un cambio profundo, y al principio genera errores nuevos que asustan. Esta lección te da el mapa para entenderlos y resolverlos sin frustración.
- Qué es la “concurrencia estricta” y por qué importa.
- Los errores típicos que verás al activarla.
- Cómo resolver cada uno con calma.
- La estrategia de migración sensata.
Qué cambia
Antes, un data race era un bug de tiempo de ejecución. Con la concurrencia estricta de Swift 6, el compilador analiza tu código y rechaza compilar cualquier acceso a datos compartidos que no sea seguro. El bug deja de existir porque no llega a ejecutarse.
Es tentador ver los errores de concurrencia estricta como el compilador “poniéndose pesado”. Dale la vuelta: cada uno de esos errores es un data race real que, sin Swift 6, te habría explotado en producción de forma aleatoria e irreproducible. El compilador está haciendo, gratis y por adelantado, el trabajo de depuración más difícil que existe. La fricción inicial es la factura de una tranquilidad enorme después: apps concurrentes que, sencillamente, no tienen esa clase de bugs.
Los errores que verás (y sus arreglos)
“Capture of ‘x’ with non-Sendable type”
Estás pasando algo no seguro a una tarea. Arreglo: hazlo un tipo de valor (struct) inmutable, o márcalo Sendable si de verdad lo es.
“Main actor-isolated property can not be referenced from a non-isolated context”
Tocas la UI desde fuera del hilo principal. Arreglo: marca la función o la clase con @MainActor, o envuelve el acceso en await MainActor.run { … }.
“Sending ‘x’ risks causing data races”
Mueves un objeto mutable entre contextos concurrentes. Arreglo: protégelo con un actor, o pasa una copia inmutable.
La estrategia sensata
Empieza main-actor
En versiones recientes, tu app arranca en el hilo principal por defecto. La mayoría del código ni se entera de la concurrencia.
Aísla lo pesado
Manda a segundo plano solo el trabajo costoso (red, procesamiento). Ahí, y solo ahí, piensas en actores y Sendable.
Migra por partes
En proyectos existentes, activa la comprobación módulo a módulo, no todo de golpe. Resuelve los avisos poco a poco.
Cuando la concurrencia estricta te marque un error, no busques cómo silenciarlo — pregúntate qué te está diciendo. Casi siempre la respuesta correcta es una de tres: “este tipo debería ser un valor inmutable”, “esto debería correr en el actor principal”, o “esto debería estar protegido por un actor”. Aprender a leer estos errores como pistas de diseño, en lugar de obstáculos, es lo que convierte la concurrencia de Swift 6 de una barrera en una superpotencia.
- Provoca a propósito un error de Sendable pasando una clase mutable a un
Tasky léelo con calma. - Resuélvelo convirtiéndola en una
structinmutable. - Toca una propiedad de UI desde una tarea de fondo y arréglalo con
@MainActor. - Anota, para tu próximo proyecto, la estrategia “empieza main-actor, aísla lo pesado”.