@Stateマクロ — Xcode 27でコンパイルが通らなくなるコード
Appleのリリースノートは、iOS 27の@Stateの項目を、SwiftUIがiOS 13から抱え続けてきたバグの説明から書き起こしています。3「初期値に式を指定して宣言された@Stateは、ビュー構造体が再生成されるたびにその式を評価していました。@State private var model = Model()の場合、これはビューのライフタイム全体を通じてModel.init()が何度も呼ばれることを意味します」1
修正の中身は書き直しです。「Xcode 27では、この繰り返し評価を回避する新しい@State実装を導入しました。この新しい挙動は、iOS 17に相当するOSまでバックデプロイされます。新しい@StateはSwiftマクロで実装されており、いくつかの例外を除いて、プロパティラッパー版とおおむねソース互換です」1
この一文にトリガーが書かれています。Appleが名前を挙げているのはXcodeであって、デプロイメントターゲットではありません。
要点
- Xcode 27は
@StateをSwiftマクロとして再実装します。Appleのシンボルページは、この切り替えを双方向から明記しています。State構造体のページには「Xcode 27以降でビルドする場合、システムは代わりにState()マクロを使用します」とあり、State()マクロのページには「Xcode 26以前でビルドする場合、システムは代わりにStateプロパティラッパーを使用します」とあります。23 - デプロイメントターゲットでマクロを避けることはできません。置き換え対象のプロパティラッパーと同じ iOS 13.0 からの利用可能性を持ち、切り替えの鍵を握るのはターゲットではなくXcodeのバージョンだからです。一方、ランタイム側の変更はiOS 17に相当するOSまでしかバックデプロイされないため、iOS 15や16をサポートするプロジェクトは、ランタイムの恩恵なしにコンパイル時の変更だけを受け取ることになります。
- 値が黙って捨てられる挙動そのものは以前からあり、変わっていません。Appleは「この挙動はマクロによって変わったわけではありませんが、そうしたケースの一部はコンパイルが通らなくなります」と書いています。1 マクロは、イニシャライザの値を飲み込んでいたバグをビルド失敗へと変換するわけです。
- コンパイルが壊れるのは2つのパターンです。宣言部に初期値を持つ
@Stateプロパティにイニシャライザから代入しているケースと、全メンバーがprivateな構造体に対してコンパイラが合成するメンバーワイズイニシャライザを、extensionから呼び出しているケース。1 ただしAppleは「そうしたケースの一部」と書いていて、すべてとは言っておらず、どれが該当するかを列挙してもいません。 - 執筆前に、リリース済みのアプリ4本を実地調査しました。
@State宣言は267件、うち宣言部に初期値を持つものが201件、2つの破壊パターンはいずれもゼロ件、惜しい1件、そしてmacOS上では偽の「問題なし」を量産してしまうgrepの書き方が1つ見つかりました。6
この項目が置かれているのは iOS および iPadOS 27 リリースノートのSwiftUIセクションであり、Xcode 27のリリースノートには対応する記載がありません。7 Appleが「Xcodeの変更」と説明しているものの置き場所としては奇妙で、この知らせが多くの開発者に遅れて届くであろう理由でもあります。
Appleが直したパフォーマンスのバグ
古い挙動についてのAppleの説明は、リリースノートとしては珍しく率直です。Model.init()が「ビューのライフタイム全体を通じて何度も呼ばれる」1。SwiftUIはビュー構造体をひっきりなしに再生成し、そのたびに等号の右辺の式が再評価されていました。すでに存在する状態のほうが優先されるため、結果はSwiftUIに破棄されていました。それでも処理そのものは走っていたわけです。
マクロのページは、新しい契約を一文で言い切っています。「State()プロパティは、SwiftUIがそのビューを最初に生成したときに既定値をインスタンス化します」2
AppleのSwiftUIアップデートのページには、リリースノートが省いた条件が加えられています。そして計画を立てるうえで重要なのは、まさにその条件のほうです。「App、Scene、Viewで@State属性がState()マクロを使って状態値を作るようにするには、プロジェクトをXcode 27以降でビルドしてください。この変更でプロパティの初期化と保存が一度だけになるのは、それがクラスである場合に限られます」4
「クラスである場合」という限定は効果の範囲をかなり狭めますが、同時に、現代のSwiftUIコードベースに溢れているパターンをまっすぐ指し示してもいます。@Observableなオブジェクトを@Stateに保持するのはApple自身が文書化しているやり方で、マクロページの例もまさにその形で@Observable class Libraryを保持しています。2 構造体のイニシャライザなら通常は安価です。しかしストアを開き、クエリを開始し、オブザーバを登録するクラスのイニシャライザは安価ではありません。そしてAppleは、それが「何度も」走ると書いているのです。1
実際に変わったもの、変わっていないもの
Appleは意味論とコンパイル挙動を一文にまとめており、その前半と後半は逆の方向を向いています。「@Stateの宣言で初期値を与えつつ、イニシャライザでも値を代入しようとした場合、イニシャライザ側の値は破棄されます。この挙動はマクロによって変わったわけではありませんが、そうしたケースの一部はコンパイルが通らなくなります」1
コードの意味は何ひとつ変わっていません。プロパティラッパーの下では、宣言部に初期値を持つ@Stateプロパティへイニシャライザから代入しても何も起こらず、しかも警告ひとつなくコンパイルが通りました。マクロはルールには手をつけず、沈黙だけを奪ったのです。
引退した失敗モードは、代償の大きいほうでした。開発者がイニシャライザを書き、タイトルを引き渡し、描画されたのは違うタイトルで、原因を探してビューのbodyを掘り返す。コンパイラは最初から知っていたのに、それを伝える手段を持たなかったわけです。
Apple自身のサンプルには、この点を突く2行のコメントが並んでいます。
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
}
}
「効果がない」と「コンパイルが通らない」が隣り合った行に並んでいます。前者がXcode 26の話、後者がXcode 27の話。同じコード、同じ意味で、下される判定だけが違うのです。
修正は、宣言部の初期値を取り除くことです。
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はこのルールを一つの指示にまで削ぎ落としています。「イニシャライザ経由で初期値を代入する場合は、@Stateの宣言で初期値を与えないでください」1
したがって正確な要約は、「マクロがイニシャライザでの代入を壊した」ではありません。イニシャライザでの代入はもともと壊れていて、マクロはそれを初めて声に出したものです。この変更を退行と位置づける説明は向きを取り違えています。とはいえ、リリースブランチにとっての実務上の帰結は同じです。昨日通っていたビルドが、今日は落ちます。
保留を1つ持っておく価値があります。Appleが書いたのは「そうしたケースの一部」であって、すべてではなく、どれが該当するかも列挙していません。Xcode 27でビルドが通ったという事実は、あなたのコードについての証拠ではあっても、ルールについての証明ではないのです。
合成イニシャライザが消える
2つ目の例外は初期値とはまったく無関係で、呼び出し側で@Stateに一切触れていないコードを巻き込みます。
「構造体の格納メンバーがすべてprivateである場合、コンパイラは同じ型のextensionから使えるprivateなinitを合成します」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
}
}
「stateマクロはこの合成イニシャライザを無効化します。そのため上記のコードはコンパイルが通らなくなります。回避するには、各メンバーへ明示的に値を代入してください」1
extension StickerPageView {
init(title: String, _ page: StickerPage) {
self.title = title
self.page = page
}
}
このパターンは1つ目より厄介です。壊れる呼び出し箇所が、原因となる@Stateとは別の宣言の中にあるからです。@Stateをgrepしても浮かび上がってきません。
Appleは結果だけを述べて、そこで筆を止めています。公開されているマクロの宣言は、その症状と辻褄が合います。
@attached(accessor, names: named(init), named(get), named(set))
@attached(peer, names: prefixed(`_`), prefixed(`__`), prefixed(`$`))
macro State()
getとsetを供給するアクセサマクロは、コンパイラから見たプロパティの性質そのものを変えます。そしてメンバーワイズイニシャライザの合成は格納プロパティを土台にしています。2 この宣言を原因として読むのはAppleの主張ではなく私の推論ですが、回避策のほうは仕組みに依存しません。代入を手で書き下すだけです。
ジェネリック推論とプロパティラッパーとの組み合わせ
残る例外について、Appleはそれぞれ一文しか割いていません。どちらも多くのプロジェクトに当たるものではありませんが、移行チェックリストには書き留めておく価値があります。
ジェネリック推論の扱いは、この項目のなかで最も漠然としています。「まれな状況で、@Stateのジェネリック引数の自動推論がマクロ実装では柔軟でなくなる場合があります。型をより具体的に書いてください」1 Appleは具体例を挙げず、手がかりになる診断メッセージも示していません。回避策は宣言に明示的な型注釈を付けることで、コンパイラが文句を言った箇所に適用します。
組み合わせについては、破壊ではなく制限として述べられています。「@Stateを他のプロパティラッパーやマクロと組み合わせることはサポートされません」1 自作のプロパティラッパーで@Stateを包んだ経験があるなら確認しておくべきですし、Appleがこれを「かつて動いていたもの」ではなく「サポート対象外の領域」として位置づけている点も覚えておくとよいでしょう。
デプロイメントターゲットでは逃げられない
Appleの3つのページから引いた3つの文が、逃げ道をすべて塞ぎます。
State()マクロのシンボルは iOS 13.0、iPadOS 13.0、macOS 10.15、tvOS 13.0、watchOS 6.0、visionOS 1.0 からの利用可能性を持ち、置き換え対象のプロパティラッパーと一致しています。つまり最低要件を下げてもマクロはかわせません。23 しかも切り替えの鍵を握るのはターゲットではなくコンパイラです。「Xcode 27以降でビルドする場合、システムは代わりにState()マクロを使用します」3
この変更のランタイム側には、コンパイル時側にはない下限があります。Appleは新しい挙動が「iOS 17に相当するOSまでバックデプロイされる」と書いており、その下に空白が残ります。iOS 15や16をデプロイメントターゲットにしているプロジェクトは、コンパイル時にはマクロを、それに伴うソース互換性の例外もろとも受け取りますが、バックデプロイされるランタイム挙動は手に入りません。1 そうしたターゲットが代わりに何を得るのかについて、Appleは何も述べていません。iOS 17より古いOSをサポートしているなら、ビルドの破壊は確実なものとして扱い、初期化が繰り返される問題の修正は最も古い端末では未確認として扱ってください。
Xcode 27でプロジェクトを開いてビルドすれば、そこにあるのは新しい@Stateです。Info.plistのキーもビルド設定も利用可能性チェックも、この判定には一切関与しません。
27サイクルには、開発者がひとまとめに語りがちな破壊的変更が3つあり、それぞれ発火する瞬間が違います。起動画面の要件は「27.0のSDK以降でビルドされたアプリ」を縛り、代償はApp Storeでのリジェクトです。シーンライフサイクルの義務化は「最新のSDKでビルドされた」アプリを縛り、代償は起動しないアプリです。@Stateマクロが縛るのはXcodeのバージョンで、代償はビルドそのもの。Appleは前の2つをSDKに、3つ目をツールチェーンに紐づけており、その結果@Stateが真っ先に来ます。plistのキーにもデプロイメントターゲットにも触れないうちに、最初のビルドで出くわすのです。
そのツールチェーンを開かざるを得なくなる圧力には公表済みの期限がありますが、iOS 27についてはまだありません。Appleの要件ページは現在こう書かれています。「2026年4月28日以降、App Store Connectにアップロードされるアプリは、iOS 26、iPadOS 26、tvOS 26、visionOS 26、watchOS 26 のSDKを用い、Xcode 26以降でビルドされている必要があります」5 iOS 27のSDKについて、Appleは同等の日付を公表していません。ここ数年、Appleは春ごとにSDKの最低要件を引き上げてきたので、27の期限も妥当な予想ではありますが、事実ではありません。他所で目にする具体的な日付はいずれも推測です。
リリース済みアプリ4本の実態
他人のコードについて書く前に、まず自分のコードで調査を回しました。App Storeでリリース済みのSwiftUIアプリ4本、いずれも現在はXcode 26.6でビルドしています。6
| アプリ | Swiftファイル数 | @State宣言数 |
宣言部に初期値あり | @Stateを宣言する型 |
|---|---|---|---|---|
| Reps | 77 | 120 | 83 | 31 |
| Return | 57 | 57 | 42 | 14 |
| Ace Citizenship | 26 | 63 | 54 | 11 |
| Banana List | 55 | 27 | 22 | 8 |
| 合計 | 215 | 267 | 201 | 64 |
作業を絞り込むコマンドは2つです。1つ目は初期値を持つ@State宣言を見つけるもので、@Stateのあとの文字クラスがしっかり仕事をします。[^A-Za-z0-9_]があることで@StateObjectが結果から外れる、単に@Stateを検索しただけでは得られない挙動です。
grep -rn --include="*.swift" \
--exclude-dir=.build --exclude-dir=DerivedData --exclude-dir=build \
-E '@State[^A-Za-z0-9_][^=]*[^!<>=]=[^=]' .
このコマンドは、属性と宣言が同じ行にあることを前提にしています。private var page = StickerPage()の上の行に@Stateを単独で書いたプロパティはマッチせず、これは後述する偽の「問題なし」が別の姿をとったものにすぎません。ヒットしなかった箇所は「問題なし」ではなく「まだ未確認」と読んでください。
2つ目は、イニシャライザも宣言しているファイル、つまり1つ目の例外が牙をむき得る唯一の場所へと絞り込みます。
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
このループはxargsへパイプするより大げさに見えますが、macOSではその重さに見合う働きをします。BSD版のgrepは、GNU版のgrepとは違って-ZでNUL区切りを出力しません。そのためgrep -rlZ ... | xargs -0 grep -lは、改行で連結された1つの塊を2つ目のgrepに渡してしまいます。パスに空白を含むプロジェクト、たとえばBanana Listのようなケースでは、標準エラー出力に「No such file or directory」が画面いっぱいに並び、標準出力には何も出てきません。これがちょうど、調査完了で問題なしという結果に見えるのです。6 空の出力を「マッチなし」と読むと、最も確認が必要なプロジェクトほど答えを取り違えることになります。
Swiftファイル215本から絞り込まれた候補は20本でした。内訳はRepsが9本、Returnが6本、Ace Citizenshipが3本、Banana Listが2本です。この20本を手で読み通した結果は、4プロジェクトすべてで同じでした。
- Appleが示した1つ目の形、つまり宣言部の初期値と、同じ型のイニシャライザ内での同一プロパティへの代入が揃っているケース: ゼロ。
- 2つ目の例外、
@Stateを宣言する構造体の合成メンバーワイズイニシャライザをextensionから呼び出しているケース: ゼロ。 - 組み合わせの例外、1つの宣言で
@Stateが他のプロパティラッパーやマクロと同居しているケース: ゼロ。
惜しい1件は書き留めておく価値があります。Appleが「取り除け」と指示した形まで、あと1行というところにいるからです。Repsのプロフィール設定ビューは@State private var healthWriteStatus: HealthAuthorizationState = .notRequestedと宣言し、そのうえでイニシャライザの中でself._healthWriteStatus = State(initialValue: ...)と代入しています。両方の場所に値があるので、Appleの回避策の一文がそのまま当てはまります。@Stateの宣言で初期値を与えないこと。1 ただしこの代入はAppleの例にあるラップ値の形ではなくアンダースコア形式を使っており、Appleのリリースノートはアンダースコア形式について一切触れていません。
そして、この調査では答えの出なかった問いが残ります。_x = State(initialValue:)というイディオムは4本のうち3本で計15回登場し、イニシャライザの引数から状態を初期化する標準的な手段であり続けています。Appleの項目はこれに触れていません。マクロの宣言はたしかにアンダースコア接頭辞のpeerを生成しますが2、それは示唆であって保証ではありません。私の環境はXcode 26.6(ビルド 17F113)でのビルドなので、イディオムの可否も、結果として出るコンパイルエラーの文面も検証できませんでした。6 Xcode 27のベータを持っている人なら、どちらも半日あれば決着をつけられるはずです。誰かがそれをやるまでは、エラー文字列ではなく宣言の形でコードを検索してください。
267件の宣言から導ける率直な見出しは、SwiftUIコードの大半は手つかずで通るということで、これはAppleの「おおむねソース互換」という言い方とも一致します。1 リスクを負っているのは手書きのイニシャライザを持つビューで、しかもそれらは密集します。4つのコードベース全体で、手書きのイニシャライザと初期値付きの@Stateを両方抱えていたSwiftファイルは10本に1本にも満たなかったのです。
よくある質問
_page = State(initialValue:)の呼び出しは変更が必要ですか
Appleの項目には書かれていません。アンダースコア形式はラップ値ではなく射影されたストレージへ直接代入するもので、リリースノートにはどこにも登場しません。initialValueの記述も、アンダースコアの例も、可否についての言及もないのです。1 マクロの公開宣言はたしかに_接頭辞のpeerを生成しますが、これは示唆であって保証ではありません。2 調査した4本のうち3本がこのイディオムを合計15回使っており、文書化された2つの例外よりも多くのコードベースに関わる問題です。6 Appleが言及するまでは、推測でリファクタリングするのではなく、Xcode 27でプロジェクトをビルドしてコンパイラに答えさせてください。
イニシャライザで代入した値の扱いは、マクロによって変わったのですか
いいえ。Appleは、破棄される挙動は「マクロによって変わったわけではありませんが、そうしたケースの一部はコンパイルが通らなくなります」と明言しています。1 Xcode 26では、宣言部にすでに初期値を持つ@Stateプロパティへ代入するイニシャライザは、何も起こさないままコンパイルが通っていました。Xcode 27では、そのうち一部がビルドに失敗します。意味論はそのままで、診断だけが届くようになったのですから、ここでビルドが壊れるということは、もともと抱えていたバグをコンパイラが報告しているということです。
自分のプロジェクトでリスクのあるコードはどう探せばよいですか
初期値を持つ@State宣言を検索し、その結果をイニシャライザも宣言しているファイルに絞り込んだうえで、その候補を手で読んでください。@StateObjectは文字クラス(@State[^A-Za-z0-9_])で除外します。またmacOSではgrep -rlZ | xargs -0ではなくfind -print0のループを使ってください。BSD版のgrepはNUL区切りを出力しないため、空白を含むパスがあると、合格に見える空の出力が返ってきます。6 アプリ4本、Swiftファイル215本から絞り込まれた候補は20本でした。ビュー構造体に対してself.init(...)を呼ぶextensionは別途検索してください。2つ目の例外は、原因となる@Stateの近くには痕跡を残さないからです。
実際にアプリは速くなりますか
速くなるのは特定の条件下だけで、しかもAppleはリリースノートが示唆するよりさらに条件を狭めています。リリースノートは繰り返しの評価を回避すると一般論で書いていますが1、SwiftUIアップデートの項目は、この変更で「プロパティの初期化と保存が一度だけになるのは、それがクラスである場合に限られます」と述べています。4 効果が現れるのは@State private var model = SomeObservableClass()のような箇所で、旧実装ではビューが再生成されるたびにクラスのイニシャライザが走り、その結果が捨てられていました。@State private var isPresented = falseはもともと問題ではなかったのです。
要点のまとめ
iOS開発者へ:
- 探すべき形は1つではなく2つです。1つ目はイニシャライザの隣にある@State宣言に、2つ目は格納メンバーがすべてprivateなビュー構造体に対してself.init(...)を呼ぶextensionの中にあります。1
- 1つ目を直すときは、イニシャライザ側の代入ではなく宣言部の初期値を削ってください。Appleの指示は、イニシャライザを唯一の供給源として残し、宣言は裸のままにするというものです。1
古いSwiftUIコードを保守しているチームへ:
- レビューの手間はコードベース全体ではなく候補リストに対して見積もってください。初期値付きの@Stateと手書きのイニシャライザを両方持つファイルは、私の4アプリでは215本中20本で、1つ目のパターンの全事例は必ずそのどれかに存在します。2つ目のパターンはextensionに潜むので、別途検索してください。6
- ビルドの破壊は、見つかったバグとして扱ってください。コンパイラが今になって拒否している、そのイニシャライザの値をSwiftUIはすでに捨てていたのですから、この変更が牙をむく箇所では、もともと何らかの挙動が間違っていたということです。1
リリース管理者へ:
- @Stateの調査は、同じサイクル内のSDK起因の作業より前に計画してください。起動画面のキーもシーンライフサイクルも、ビルド対象のSDKに紐づきます。一方@Stateが紐づくのはビルドに使うXcodeなので、こちらが先に来ます。13
- iOS 27のSDKの期限を前提に計画を立てないでください。Appleが公表している最低要件は依然としてiOS 26のSDKで、2026年4月28日以降必須とされており、27については何も告知されていません。5
1つのサイクルで3つの強制ポイントが出荷され、それぞれ別の場所で失敗します。起動画面のキーは申請を止め、シーンの義務化は起動を止め、@Stateマクロはビルドを止めます。同じSDKに含まれる残りの変更については、iOS 27のSwiftUI新機能をご覧ください。シリーズ全体のハブはAppleエコシステム・シリーズです。
参考文献
-
Apple, iOS & iPadOS 27 Release Notes, SwiftUI section, New Features (radar 105893279). 出典: 旧挙動の説明(”A
@Statedeclared 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 meansModel.init()gets called many times throughout the view’s lifetime”)、新実装(”Xcode 27 introduces a new@Stateimplementation that avoids this repeated evaluation. This new behavior back-deploys to iOS 17 aligned OSes. The new@Stateis implemented with a Swift macro. It is largely source compatible with the property wrapper version, with a few exceptions”)、1つ目の例外とその指示(”If you provide an initial value at@Statedeclaration, and also try to assign a value to it in an initializer, the initializer value is discarded. This behavior has not changed because of the macro, but some such cases no longer compile” および “When assigning initial value via an initializer, do not provide an initial value at the @State declaration”)、1つ目の例外に関する2つのStickerPageViewコードリスト、2つ目の例外(”When all stored members of a struct are private, the compiler synthesizes a private init that can be used in an extension of the same type” および “The state macro disables this synthesized initializer. So the code above no longer compiles. To mitigate, assign value to members explicitly”)とその2つのコードリスト、ジェネリック推論についての注記(”In rare situations, the automatic inference of generic arguments of@Stateis less flexible with the macro implementation. Write the type with more specificity”)、組み合わせについての注記(”Composing@Statewith other property wrappers or macros is not supported”)。コードリストはすべて原文のまま再掲。2026年7月25日、AppleのドキュメントJSONに対して検証。HTMLのページはJavaScript経由で内容を描画するため。 ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩ -
Apple, State() macro, SwiftUI macro reference. 出典: 公開されている宣言(
@attached(accessor, names: named(init), named(get), named(set))、@attached(peer, names: prefixed(_), prefixed(__), prefixed($))、macro State())、利用可能性の一覧(iOS 13.0、iPadOS 13.0、Mac Catalyst 13.0、macOS 10.15、tvOS 13.0、visionOS 1.0、watchOS 6.0)、ツールチェーンについての補足(”When you build with Xcode 26 or earlier, the system uses theStateproperty wrapper instead”)、新しい初期化の契約(”AState()property instantiates its default value the first time SwiftUI instantiates the view”)、および@Observable class Libraryを@Stateに保持する “Store observable objects” の例。 ↩↩↩↩↩↩↩ -
Apple, State, SwiftUI structure reference. 依然として
@frozen @propertyWrapper struct State<Value>と宣言されており、利用可能性は iOS 13.0、iPadOS 13.0、Mac Catalyst 13.0、macOS 10.15、tvOS 13.0、visionOS 1.0、watchOS 6.0 から。逆方向を指すツールチェーンの補足の出典: “When you build with Xcode 27 or later, the system uses theState()macro instead.” ↩↩↩↩↩ -
Apple, SwiftUI Updates, June 2026, General. クラス限定の条件の出典: “Build your project in Xcode 27 or later so that the
@Stateattribute uses theState()macro to create a state value in anApp,Scene, orView. This change only initializes and stores your property once when it’s a class.” ↩↩ -
Apple, Upcoming requirements, Apple Developer News. 現行のSDK最低要件の出典: “Since April 28, 2026 Apps uploaded to App Store Connect must be built with Xcode 26 or later using an SDK for iOS 26, iPadOS 26, tvOS 26, visionOS 26, or watchOS 26.” 2026年7月25日に確認。iOS 27のSDKに言及する要件はページに掲載されていない。 ↩↩
-
著者によるリリース済みSwiftUIアプリ4本(Reps、Return、Ace Citizenship、Banana List)の調査。macOS 26.5.2、Xcode 26.6(ビルド 17F113)、2026年7月25日。件数は、各型宣言を波括弧の深さで解析しイニシャライザ本体をその内側に限定して数えるスクリプトによるもので、上掲の
grepコマンドと相互検証し、4プロジェクトすべてで宣言部の初期値の件数(83、42、54、22)が正確に一致した。BSD版grepの挙動は直接確認済み。macOSではgrep -rlZがNUL区切りではなく改行区切りで出力するため、xargs -0は連結された単一の引数を受け取り、空白を含むパスがあるとパイプラインは “No such file or directory” で失敗する。_x = State(initialValue:)イディオムの件数(Reps、Return、Banana Listにまたがる15箇所)も同じ調査によるもの。Xcode 27での挙動は検証しておらず、コンパイルエラーの文面もここには記載していない。使用したマシンにXcode 27がインストールされていなかったため。 ↩↩↩↩↩↩↩ -
Apple, Xcode 27 Release Notes. 2026年7月25日に radar 105893279 と
@Stateマクロを記述する項目を検索したが、いずれも見当たらなかった。@Stateへの言及は、無関係なMusicKitの修正(radar 176947544)が唯一である。 ↩