The @State Macro: What Xcode 27 Stops Compiling
Apple’s iOS 27 release notes open the @State entry by describing a bug SwiftUI has carried since iOS 13:3 “A @State declared with an expression as its initial value used to evaluate the expression each time the view struct re-instantiates. In the case of @State private var model = Model(), this means Model.init() gets called many times throughout the view’s lifetime.”1
The fix is a rewrite. “Xcode 27 introduces a new @State implementation that avoids this repeated evaluation. This new behavior back-deploys to iOS 17 aligned OSes. The new @State is implemented with a Swift macro. It is largely source compatible with the property wrapper version, with a few exceptions.”1
Read the trigger in that sentence. Apple names Xcode, not a deployment target.
TL;DR
- Xcode 27 reimplements
@Stateas a Swift macro, and Apple’s symbol pages state the switch in both directions: theStatestructure page says “When you build with Xcode 27 or later, the system uses theState()macro instead,” and theState()macro page says “When you build with Xcode 26 or earlier, the system uses theStateproperty wrapper instead.”23 - Your deployment target cannot opt out of the macro. It carries the same iOS 13.0 availability as the property wrapper it replaces, and the switch keys off the Xcode version rather than the target. The runtime half back-deploys only to “iOS 17 aligned OSes,” so projects supporting iOS 15 or 16 get the compile-time change without it.
- The silent-discard behavior is old and unchanged. Apple writes that it “has not changed because of the macro, but some such cases no longer compile.”1 The macro converts a bug that ate your initializer’s value into a build failure.
- Two patterns are where compilation breaks: an initializer assigning to a
@Stateproperty that also carries a declaration-site initial value, and an extension calling the memberwise initializer the compiler synthesizes for an all-private struct.1 Apple writes “some such cases,” not all, and never enumerates which. - I …