← Todos los articulos

La macro @State: lo que Xcode 27 deja de compilar

Las notas de la versión de iOS 27 de Apple abren la entrada sobre @State describiendo un error que SwiftUI arrastra desde iOS 13:3 “Un @State declarado con una expresión como valor inicial evaluaba esa expresión cada vez que la struct de la vista se reinstanciaba. En el caso de @State private var model = Model(), esto significa que Model.init() se llama muchas veces a lo largo del ciclo de vida de la vista”.1

La corrección es una reescritura. “Xcode 27 introduce una nueva implementación de @State que evita esa evaluación repetida. Este nuevo comportamiento está disponible de forma retroactiva en los sistemas alineados con iOS 17. El nuevo @State está implementado con una macro de Swift. Es en gran medida compatible a nivel de código fuente con la versión basada en property wrapper, con algunas excepciones”.1

Fíjate en el disparador de esa frase: Apple nombra Xcode, no un deployment target.

En resumen

  • Xcode 27 reimplementa @State como una macro de Swift, y las páginas de símbolos de Apple documentan el cambio en ambas direcciones: la página de la estructura State dice “Cuando compilas con Xcode 27 o posterior, el sistema usa la macro State() en su lugar”, y la página de la macro State() dice “Cuando compilas con Xcode 26 o anterior, el sistema usa el property wrapper State en su lugar”.23
  • El deployment target no te permite quedarte fuera de la macro: tiene la misma disponibilidad desde iOS 13.0 que el property wrapper al que reemplaza, y el cambio depende de la versión de Xcode, no del target. La mitad que vive en tiempo de ejecución solo llega de forma retroactiva a los “sistemas alineados con iOS 17”, así que los proyectos que soportan iOS 15 o 16 reciben el cambio en tiempo de compilación sin ese beneficio.
  • El descarte silencioso es viejo y no cambió. Apple escribe que “no ha cambiado a causa de la macro, pero algunos de esos casos ya no compilan”.1 La macro convierte un error que se comía el valor de tu inicializador en un fallo de compilación.
  • La compilación se rompe en dos patrones: un inicializador que asigna a una propiedad @State que además lleva un valor inicial en su declaración, y una extensión que llama al inicializador por miembros que el compilador sintetiza para una struct con todos sus miembros privados.1 Apple escribe “algunos de esos casos”, no todos, y nunca enumera cuáles.
  • Antes de escribir audité cuatro apps publicadas: 267 declaraciones @State, 201 de ellas con valor inicial en la declaración, cero casos de ninguno de los dos patrones que rompen la compilación, uno que se salva por poco y una fórmula de grep que fabrica resultados falsamente limpios en macOS.6

La entrada vive en las notas de la versión de iOS y iPadOS 27, dentro de la sección de SwiftUI, y no en las notas de Xcode 27, que no incluyen nada equivalente.7 Un sitio extraño para un cambio que Apple atribuye a Xcode, y una buena razón para que la noticia le llegue tarde a mucha gente.

El error de rendimiento que Apple corrigió

La descripción que hace Apple del comportamiento antiguo es inusualmente directa para una nota de versión: Model.init() “se llama muchas veces a lo largo del ciclo de vida de la vista”.1 SwiftUI reinstancia las structs de las vistas constantemente, y cada reinstanciación volvía a evaluar la expresión a la derecha del signo igual. SwiftUI descartaba el resultado, porque el estado que ya existe gana, pero el trabajo se hacía igual.

La página de la macro enuncia el nuevo contrato en una sola frase: “Una propiedad State() instancia su valor por defecto la primera vez que SwiftUI instancia la vista”.2

La página de novedades de SwiftUI añade un matiz que la nota de versión omite, y ese matiz es justamente la parte que conviene tener en cuenta al planificar: “Compila tu proyecto en Xcode 27 o posterior para que el atributo @State use la macro State() al crear un valor de estado en un App, una Scene o una View. Este cambio solo inicializa y almacena tu propiedad una vez cuando se trata de una clase”.4

“Cuando se trata de una clase” recorta bastante la ganancia, y apunta directo al patrón del que están llenas las bases de código modernas de SwiftUI. Guardar un objeto @Observable dentro de @State es el enfoque documentado por Apple, y el propio ejemplo de la página de la macro sostiene una @Observable class Library exactamente así.2 El inicializador de una struct suele ser barato; el de una clase que abre un almacén, lanza una consulta o registra un observador no lo es, y Apple describe que se ejecuta “muchas veces”.1

Qué cambió de verdad y qué no

Apple enuncia la semántica y el comportamiento de compilación en una sola frase, y las dos mitades apuntan en direcciones opuestas: “Si proporcionas un valor inicial en la declaración de @State y además intentas asignarle un valor en un inicializador, el valor del inicializador se descarta. Este comportamiento no ha cambiado a causa de la macro, pero algunos de esos casos ya no compilan”.1

Nada de lo que el código significa cambió. Con el property wrapper, un inicializador que asignaba a una propiedad @State con valor en su declaración no hacía nada, en silencio, y compilaba sin quejas. La macro deja la regla intacta y elimina el silencio.

El modo de fallo que desaparece es el caro: alguien escribe un inicializador, hace pasar un título por él, ve que se renderiza el título equivocado y se va a buscar el problema al cuerpo de la vista. El compilador lo sabía desde el principio y no tenía forma de decirlo.

El propio ejemplo de Apple lleva los dos comentarios que lo dejan claro:

struct StickerPageView: View {
    @State private var page = StickerPage()
    let title: String

    init(title: String) {
        // `title` won't have any effect
        // this also won't compile with @State macro
        self.page = StickerPage(title: title)
        self.title = title
    }
}

“No tendrá ningún efecto” y “no compilará” están en líneas contiguas. La primera describe Xcode 26; la segunda, Xcode 27. El mismo código, el mismo significado, distinto veredicto.

La corrección elimina el valor de la declaración:

struct StickerPageView: View {
    @State private var page: StickerPage // no initial value expression
    let title: String

    init(title: String) {
        self.page = StickerPage(title: title) // works!
        self.title = title
    }
}

Apple reduce la regla a una sola instrucción: “Cuando asignes el valor inicial mediante un inicializador, no proporciones un valor inicial en la declaración de @State”.1

Así que el resumen exacto no es que la macro haya roto la asignación desde el inicializador: esa asignación ya estaba rota, y la macro es lo primero que lo dice en voz alta. Quien presente el cambio como una regresión tiene la dirección al revés, aunque la consecuencia práctica para una rama de publicación sea idéntica: compilaciones que ayer pasaban hoy fallan.

Conviene quedarse con una salvedad. Apple escribió “algunos de esos casos”, no todos, y nunca enumera cuáles. Una compilación limpia con Xcode 27 es evidencia sobre tu código, no prueba sobre la regla.

El inicializador sintetizado desaparece

La segunda excepción no tiene nada que ver con los valores iniciales, y atrapa código que ni siquiera menciona @State en el punto de llamada.

“Cuando todos los miembros almacenados de una struct son privados, el compilador sintetiza un init privado que puede usarse en una extensión del mismo tipo:”1

struct StickerPageView: View {
    @State private var page: StickerPage
    private let title: String
    ...
}

extension StickerPageView {
    init(title: String, _ page: StickerPage) {
        self.init(page: page, title: title) // using the synthesized init
    }
}

“La macro state desactiva ese inicializador sintetizado, así que el código anterior ya no compila. Para mitigarlo, asigna el valor a los miembros de forma explícita:”1

extension StickerPageView {
    init(title: String, _ page: StickerPage) {
        self.title = title
        self.page = page
    }
}

Este patrón es más desagradable de encontrar que el primero, porque el punto de llamada que se rompe vive en una declaración distinta de la del @State que lo provoca. Buscar @State con grep no lo saca a la luz.

Apple enuncia el efecto y se detiene ahí. La declaración publicada de la macro encaja con el síntoma:

@attached(accessor, names: named(init), named(get), named(set))
@attached(peer, names: prefixed(`_`), prefixed(`__`), prefixed(`$`))
macro State()

Una macro de accesores que aporta get y set cambia lo que la propiedad es a ojos del compilador, y la síntesis del inicializador por miembros se apoya en las propiedades almacenadas.2 Leer la declaración como la causa es una inferencia mía, no una afirmación de Apple, y la mitigación no depende del mecanismo: escribe las asignaciones a mano.

Inferencia de genéricos y composición con property wrappers

Apple le dedica una frase a cada una de las excepciones restantes, y ambas merecen una nota en una lista de verificación de migración aunque ninguna vaya a golpear a muchos proyectos.

La inferencia de genéricos recibe el trato más vago de toda la entrada: “En situaciones poco frecuentes, la inferencia automática de los argumentos genéricos de @State es menos flexible con la implementación basada en macro. Escribe el tipo con mayor especificidad”.1 Apple no nombra ningún caso ni ofrece ningún diagnóstico que buscar. La mitigación es anotar el tipo de forma explícita en la declaración, allí donde el compilador se queje.

Apple plantea la composición como un límite y no como una ruptura: “No se admite componer @State con otros property wrappers o macros”.1 Conviene revisarlo si alguna vez envolviste @State dentro de un property wrapper propio, y conviene recordar que Apple lo presenta como terreno no soportado, no como algo que antes funcionaba.

Ningún deployment target te deja fuera

Tres frases sacadas de tres páginas de Apple cierran todas las vías de escape.

El símbolo de la macro State() declara disponibilidad desde iOS 13.0, iPadOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0 y visionOS 1.0, la misma que el property wrapper al que reemplaza, así que bajar tu mínimo no esquiva la macro.23 Y el cambio depende del compilador, no del target: “Cuando compilas con Xcode 27 o posterior, el sistema usa la macro State() en su lugar”.3

La mitad del cambio que vive en tiempo de ejecución tiene un piso que la mitad de compilación no tiene. Apple escribe que el nuevo comportamiento “está disponible de forma retroactiva en los sistemas alineados con iOS 17”, lo que deja un hueco por debajo: un proyecto que despliega a iOS 15 o 16 recibe la macro en tiempo de compilación —y con ella las excepciones de compatibilidad de código fuente— sin el comportamiento retroactivo en tiempo de ejecución.1 Apple no dice qué reciben esos targets en su lugar. Si soportas un sistema anterior a iOS 17, da por segura la ruptura de compilación y por no confirmada la corrección de la inicialización repetida en tus dispositivos más antiguos.

Abre el proyecto en Xcode 27, compila y ya tienes el nuevo @State. Ninguna clave de Info.plist, ningún ajuste de compilación y ninguna comprobación de disponibilidad entran en la decisión.

El ciclo 27 trae tres cambios que rompen la compatibilidad y que los desarrolladores insisten en archivar bajo un mismo encabezado, aunque se disparan en tres momentos distintos. El requisito de la pantalla de inicio se aplica a las “apps compiladas con el SDK 27.0 o posterior” y te cuesta un rechazo en la App Store. El mandato del ciclo de vida de escenas se aplica a las apps “compiladas con el SDK más reciente” y te cuesta una app que no arranca. La macro @State depende de la versión de Xcode y te cuesta una compilación. Apple formula los dos primeros en términos del SDK y el tercero en términos del toolchain, lo que pone a @State en primera fila: te lo encuentras en la primera compilación, antes de haber tocado una clave del plist o un deployment target.

La presión para abrir ese toolchain llega con un calendario publicado, aunque todavía no para iOS 27. La página de requisitos de Apple dice actualmente: “Desde el 28 de abril de 2026, las apps subidas a App Store Connect deben compilarse con Xcode 26 o posterior usando un SDK de iOS 26, iPadOS 26, tvOS 26, visionOS 26 o watchOS 26”.5 Apple no ha publicado una fecha equivalente para el SDK de iOS 27. Cada primavera reciente Apple ha subido el mínimo del SDK, así que una fecha límite para el ciclo 27 es una expectativa razonable, no un hecho, y cualquier fecha concreta que leas por ahí es una inferencia.

Qué contienen en realidad cuatro apps publicadas

Ejecuté la auditoría sobre mi propio código antes de escribir sobre el de nadie más: cuatro apps de la App Store, todas en SwiftUI, todas compiladas actualmente con Xcode 26.6.6

App Archivos Swift Declaraciones @State Con valor en la declaración Tipos que declaran @State
Reps 77 120 83 31
Return 57 57 42 14
Ace Citizenship 26 63 54 11
Banana List 55 27 22 8
Total 215 267 201 64

Dos comandos acotan el trabajo. El primero encuentra las declaraciones @State con valor inicial, y la clase de caracteres que va después de @State se gana su lugar: [^A-Za-z0-9_] mantiene @StateObject fuera de los resultados, cosa que una búsqueda simple de @State no hace.

grep -rn --include="*.swift" \
  --exclude-dir=.build --exclude-dir=DerivedData --exclude-dir=build \
  -E '@State[^A-Za-z0-9_][^=]*[^!<>=]=[^=]' .

El comando asume que el atributo y la declaración comparten línea. Una propiedad escrita con @State en su propia línea encima de private var page = StickerPage() no produce ninguna coincidencia, que es el mismo fallo de falsa limpieza descrito más abajo con otro disfraz. Lee las ausencias como “aún sin revisar”, no como “limpio”.

El segundo se queda con los archivos que además declaran un inicializador, el único lugar donde la primera excepción puede morder:

find . -name "*.swift" -not -path "*/build/*" -not -path "*/DerivedData/*" -print0 |
while IFS= read -r -d '' f; do
  grep -qE '@State[^A-Za-z0-9_][^=]*[^!<>=]=[^=]' "$f" || continue
  grep -qE '^[[:space:]]*(private |public |internal |fileprivate )?init[[:space:]]*[(<]' "$f" || continue
  echo "$f"
done

El bucle parece más pesado que canalizar hacia xargs, y se gana ese peso en macOS. El grep de BSD no emite separadores NUL con -Z como sí hace el grep de GNU, así que grep -rlZ ... | xargs -0 grep -l le entrega al segundo grep un único bloque unido por saltos de línea. En un proyecto cuya ruta contiene un espacio —Banana List, por ejemplo— obtienes una pantalla de “No such file or directory” en la salida de error y absolutamente nada en la salida estándar, que se lee exactamente igual que una auditoría limpia.6 Interpretar la salida vacía como “sin coincidencias” invierte la respuesta justo en los proyectos que más la necesitan.

De 215 archivos Swift, la lista corta quedó en 20: nueve en Reps, seis en Return, tres en Ace Citizenship y dos en Banana List. Leer los 20 a mano dio el mismo resultado en los cuatro proyectos.

  • La primera forma exacta de Apple, un valor inicial en la declaración más una asignación a esa misma propiedad dentro de un inicializador del mismo tipo: cero.
  • La segunda excepción, una extensión que llama al inicializador por miembros sintetizado de una struct que declara @State: cero.
  • La excepción de composición, @State junto a otro property wrapper o macro en una misma declaración: cero.

Un caso que se salva por poco merece descripción, porque está a una línea de la forma que Apple te pide eliminar. Una vista de configuración de perfil en Reps declara @State private var healthWriteStatus: HealthAuthorizationState = .notRequested y luego, dentro de su inicializador, asigna self._healthWriteStatus = State(initialValue: ...). Ambos sitios llevan un valor, así que la frase de mitigación de Apple se aplica al pie de la letra: no proporciones un valor inicial en la declaración de @State.1 La asignación usa la forma con guion bajo en vez de la forma del valor envuelto que aparece en el ejemplo de Apple, y la nota de versión nunca menciona la forma con guion bajo.

Con lo cual queda en pie la pregunta que mi auditoría no pudo responder. La fórmula _x = State(initialValue:) aparece 15 veces en tres de las cuatro apps, y sigue siendo la forma estándar de sembrar estado desde un parámetro del inicializador. La entrada de Apple no lo aborda. La declaración de la macro sí genera una declaración par con prefijo de guion bajo,2 lo cual es sugerente pero no una garantía. Compilo con Xcode 26.6 (build 17F113), así que no pude verificar ni la fórmula ni el texto de los errores de compilación resultantes.6 Cualquiera que tenga una beta de Xcode 27 puede zanjar ambas cosas en una tarde. Hasta que alguien lo haga, busca en tu código la forma de la declaración, no una cadena de error.

El titular honesto de esas 267 declaraciones es que la mayor parte del código SwiftUI pasa sin tocarse, lo que coincide con el “en gran medida compatible a nivel de código fuente” de Apple.1 Las vistas en riesgo son las que tienen inicializadores escritos a mano, y se concentran mucho: menos de uno de cada 10 archivos Swift en cuatro bases de código contenía a la vez un inicializador escrito a mano y un @State con su propio valor inicial.

Preguntas frecuentes

¿Tengo que cambiar las llamadas _page = State(initialValue:)?

La entrada de Apple no lo dice. La forma con guion bajo asigna directamente el almacenamiento proyectado en lugar del valor envuelto, y no aparece en ningún punto de la nota de versión: ni initialValue, ni un ejemplo con guion bajo, ni una mención en un sentido u otro.1 La declaración publicada de la macro sí emite una declaración par con el prefijo _, lo cual es sugerente pero no una garantía.2 Tres de las cuatro apps que audité usan esa fórmula, 15 veces en total, así que la respuesta importa a más bases de código que las dos excepciones documentadas.6 Hasta que Apple lo aclare, compila el proyecto con Xcode 27 y deja que responda el compilador, en vez de refactorizar por especulación.

¿La macro cambió lo que le pasa a un valor asignado en un inicializador?

No. Apple es explícita en que el descarte “no ha cambiado a causa de la macro, pero algunos de esos casos ya no compilan”.1 Con Xcode 26, un inicializador que asignaba a una propiedad @State que ya llevaba valor en su declaración no hacía nada y compilaba. Con Xcode 27 algunos de esos casos no compilan. La semántica se quedó donde estaba y llegaron los diagnósticos, así que una compilación que se rompe aquí es el compilador informando de un error que ya tenías.

¿Cómo encuentro el código en riesgo en mi proyecto?

Busca declaraciones @State con valor inicial, restringe los resultados a los archivos que además declaran un inicializador y luego lee esa lista corta a mano. Excluye @StateObject con una clase de caracteres (@State[^A-Za-z0-9_]) y prefiere un bucle con find -print0 antes que grep -rlZ | xargs -0 en macOS, donde el grep de BSD no emite separadores NUL y cualquier ruta que contenga un espacio produce una salida vacía que parece un aprobado.6 En cuatro apps y 215 archivos Swift, la lista corta quedó en 20 archivos. Busca aparte las extensiones que llaman a self.init(...) sobre una struct de vista, porque la segunda excepción no deja rastro cerca del @State que la provoca.

¿Mi app va a ser más rápida de verdad?

Solo en circunstancias concretas, y Apple las acota más de lo que sugiere la nota de versión. La nota describe evitar la evaluación repetida en general,1 mientras que la entrada de novedades de SwiftUI dice que el cambio “solo inicializa y almacena tu propiedad una vez cuando se trata de una clase”.4 La ganancia se concentra en @State private var model = SomeObservableClass(), donde la implementación antigua ejecutaba el inicializador de la clase en cada reinstanciación de la vista y tiraba el resultado. Un @State private var isPresented = false nunca fue el problema.

Conclusiones clave

Para desarrolladores de iOS: - Audita dos formas, no una. La primera vive en una declaración @State junto a un inicializador; la segunda, en una extensión que llama a self.init(...) sobre una struct de vista cuyos miembros almacenados son todos privados.1 - Corrige la primera borrando el valor de la declaración, no la asignación del inicializador. La instrucción de Apple es dejar el inicializador como única fuente y la declaración desnuda.1

Para equipos que mantienen código SwiftUI antiguo: - Dimensiona el tiempo de revisión según la lista corta, no según toda la base de código. Los archivos que tenían a la vez un @State con valor inicial y un inicializador escrito a mano fueron 20 de 215 en mis cuatro apps, y toda aparición del primer patrón tiene que vivir en uno de ellos. Busca el segundo patrón por separado, porque se esconde en las extensiones.6 - Trata una compilación rota como un error encontrado. SwiftUI ya estaba descartando el valor del inicializador que ahora rechaza tu compilador, así que allí donde el cambio muerda, algún comportamiento ya estaba mal.1

Para quienes gestionan las versiones: - Coloca la auditoría de @State por delante del trabajo que dispara el SDK en el mismo ciclo. Tanto la clave de la pantalla de inicio como el ciclo de vida de escenas dependen del SDK contra el que compilas; @State depende del Xcode con el que compilas, así que aterriza primero.13 - No planifiques pensando en una fecha límite del SDK de iOS 27. El mínimo publicado por Apple sigue siendo el SDK de iOS 26, obligatorio desde el 28 de abril de 2026, y Apple no ha anunciado nada para el 27.5


Tres puntos de exigencia llegan en un mismo ciclo y fallan en tres lugares distintos: la clave de la pantalla de inicio detiene un envío, el mandato de escenas detiene un arranque y la macro @State detiene una compilación. Para el resto de lo que aterriza en el mismo SDK, consulta Novedades de SwiftUI en iOS 27. El centro de toda la serie es la Serie del ecosistema Apple.

Referencias


  1. Apple, iOS & iPadOS 27 Release Notes, sección de SwiftUI, novedades (radar 105893279). Fuente de la descripción del comportamiento antiguo (“Un @State declarado con una expresión como valor inicial evaluaba esa expresión cada vez que la struct de la vista se reinstanciaba. En el caso de @State private var model = Model(), esto significa que Model.init() se llama muchas veces a lo largo del ciclo de vida de la vista”), de la nueva implementación (“Xcode 27 introduce una nueva implementación de @State que evita esa evaluación repetida. Este nuevo comportamiento está disponible de forma retroactiva en los sistemas alineados con iOS 17. El nuevo @State está implementado con una macro de Swift. Es en gran medida compatible a nivel de código fuente con la versión basada en property wrapper, con algunas excepciones”), de la primera excepción y su instrucción (“Si proporcionas un valor inicial en la declaración de @State y además intentas asignarle un valor en un inicializador, el valor del inicializador se descarta. Este comportamiento no ha cambiado a causa de la macro, pero algunos de esos casos ya no compilan” y “Cuando asignes el valor inicial mediante un inicializador, no proporciones un valor inicial en la declaración de @State”), de los dos listados de código de StickerPageView correspondientes a la primera excepción, de la segunda excepción (“Cuando todos los miembros almacenados de una struct son privados, el compilador sintetiza un init privado que puede usarse en una extensión del mismo tipo” y “La macro state desactiva ese inicializador sintetizado, así que el código anterior ya no compila. Para mitigarlo, asigna el valor a los miembros de forma explícita”) con sus dos listados de código, de la nota sobre la inferencia de genéricos (“En situaciones poco frecuentes, la inferencia automática de los argumentos genéricos de @State es menos flexible con la implementación basada en macro. Escribe el tipo con mayor especificidad”) y de la nota sobre composición (“No se admite componer @State con otros property wrappers o macros”). Todos los listados de código se reproducen literalmente. Verificado el 25 de julio de 2026 contra el JSON de la documentación de Apple, ya que la página HTML renderiza su contenido mediante JavaScript. 

  2. Apple, State() macro, referencia de macros de SwiftUI. Fuente de la declaración publicada (@attached(accessor, names: named(init), named(get), named(set)), @attached(peer, names: prefixed(_), prefixed(__), prefixed($)), macro State()), de la lista de disponibilidad (iOS 13.0, iPadOS 13.0, Mac Catalyst 13.0, macOS 10.15, tvOS 13.0, visionOS 1.0, watchOS 6.0), del inciso sobre el toolchain (“Cuando compilas con Xcode 26 o anterior, el sistema usa el property wrapper State en su lugar”), del nuevo contrato de inicialización (“Una propiedad State() instancia su valor por defecto la primera vez que SwiftUI instancia la vista”) y del ejemplo “Store observable objects”, que guarda una @Observable class Library dentro de @State

  3. Apple, State, referencia de estructuras de SwiftUI. Sigue declarada como @frozen @propertyWrapper struct State<Value> con disponibilidad desde iOS 13.0, iPadOS 13.0, Mac Catalyst 13.0, macOS 10.15, tvOS 13.0, visionOS 1.0 y watchOS 6.0. Fuente del inciso sobre el toolchain que apunta en la otra dirección: “Cuando compilas con Xcode 27 o posterior, el sistema usa la macro State() en su lugar”. 

  4. Apple, SwiftUI Updates, junio de 2026, sección general. Fuente del matiz sobre las clases: “Compila tu proyecto en Xcode 27 o posterior para que el atributo @State use la macro State() al crear un valor de estado en un App, una Scene o una View. Este cambio solo inicializa y almacena tu propiedad una vez cuando se trata de una clase”. 

  5. Apple, Upcoming requirements, Apple Developer News. Fuente del mínimo vigente del SDK: “Desde el 28 de abril de 2026, las apps subidas a App Store Connect deben compilarse con Xcode 26 o posterior usando un SDK de iOS 26, iPadOS 26, tvOS 26, visionOS 26 o watchOS 26”. Consultado el 25 de julio de 2026; la página no lista ningún requisito que haga referencia al SDK de iOS 27. 

  6. Auditoría del autor sobre cuatro apps SwiftUI publicadas (Reps, Return, Ace Citizenship y Banana List) en macOS 26.5.2 con Xcode 26.6 (build 17F113), 25 de julio de 2026. Los conteos provienen de un script que analiza cada declaración de tipo por profundidad de llaves y acota los cuerpos de los inicializadores dentro de ella, contrastado con el comando grep publicado más arriba, que reprodujo exactamente los conteos por proyecto de valores en la declaración en los cuatro casos (83, 42, 54 y 22). El comportamiento del grep de BSD se confirmó de forma directa: en macOS, grep -rlZ emite una salida separada por saltos de línea en vez de por NUL, así que xargs -0 recibe un único argumento unido y la tubería falla con “No such file or directory” en cualquier ruta que contenga un espacio. El conteo de la fórmula _x = State(initialValue:) (15 apariciones en Reps, Return y Banana List) sale de la misma pasada. El comportamiento con Xcode 27 no se probó, y aquí no se reporta ningún texto de error de compilación, porque Xcode 27 no estaba instalado en la máquina utilizada. 

  7. Apple, Xcode 27 Release Notes. Se buscó el radar 105893279 y cualquier entrada que describiera la macro @State el 25 de julio de 2026; no aparece ninguno de los dos. La única mención a @State es una corrección de MusicKit sin relación (radar 176947544). 

Artículos relacionados

Xcode 27 elimina ld64 y exige nombres de módulo únicos

Xcode 27 elimina el enlazador ld64 y exige nombres de módulo Clang únicos. Auditoría de siete proyectos y comandos proba…

23 min de lectura

La regla de la pantalla de inicio en iOS 27: cuatro claves o rechazo

Compiladas con el SDK de iOS 27, las apps deben declarar una pantalla de inicio o la App Store las rechaza: las cuatro c…

15 min de lectura