SwiftUI の画面を開くと落ちる:EXC_BAD_ACCESS の原因は、ビューの型が深すぎて「スタックを使い切る」ことだった
SwiftUI のアプリで、特定の画面を実機で開くと EXC_BAD_ACCESS で落ちました。原因は、1つの body に詰め込みすぎてビューの型が深くなり、型の情報を組み立てるだけでメインスレッドのスタックを使い切ることでした。2つのアプリで同じことが起きた記録と、直し方、再現のしかたを書きます。

SwiftUI の画面を実機で開いた時だけ EXC_BAD_ACCESS で落ちる場合、原因は「1つの body に詰め込みすぎて、ビューの型が深くなり、型の情報を組み立てるだけでメインスレッドのスタックを使い切ること」かもしれません。私たちは、録音のアプリ(TalkLens)と、不動産の業務アプリ(Kaitori Base)の2つで、同じことが起きました。直し方は、画面を独立した struct の部品に分けることでした。
特定の画面を開くと、実機でだけアプリが落ちる。コードを見ても、おかしなところが見つからない。そんな時の、原因と直し方の記録です。落ちた画面の名前や、中のデータは書きません。
症状:組織を作ったあと、録音のタブを開くと落ちる
TalkLens では、録音のタブに警告のカードなどを足したあと、組織を作った状態で録音のタブを開くと、アプリが落ちるようになりました。落ちる時の表示は EXC_BAD_ACCESS で、呼び出しの記録(スタック)には、swift_getTypeByMangledName や SubstGenericParametersFromMetadata が、何重にも並んでいました。

原因:ビューの型が深くなり、型の情報を作るだけでスタックを使い切る
SwiftUI は、画面を作る時に、ビューの型の情報を組み立てます。1つの body に、選択行、警告、送信待ちの表示などを入れ子で並べると、ビューの型がどんどん深くなります。


直し方:画面を、独立した struct の部品に分ける
直し方は、1つの body に詰め込まず、画面を独立した struct のビューに分けることでした。


同じことが、不動産の業務アプリでも起きた
Kaitori Base でも、査定のタブが実機でだけ落ちました。

最初は、Binding の書き方を変えて対策した
階層の深い Binding の動的なメンバーをやめ、明示的な Binding にしました(ビルド35)。
そのあと、根本から直した
本体と修飾を独立した構造体に分け、折りたたみの中身は、開いた時にだけ作る形にしました。
見た目は違っても、原因は同じでした。1つの body に詰め込みすぎると起きる、ということが、2つのアプリで確かめられました。
再現のしかた:スタックを小さくして、UI テストで確かめる
実機でしか落ちないと、直したかどうかを確かめにくくなります。

まとめ

- 特定の画面を実機で開くと EXC_BAD_ACCESS で落ちる原因の1つは、ビューの型が深くなって、スタックを使い切ること
- シミュレーターはスタックが大きいので、再現しにくい
- 画面を独立した struct の部品に分け、AnyView は避け、修飾子は ViewModifier にまとめる
- スタックを 1MB・512KB に絞った構成と UI テストで、再現と確認ができる
- 録音のアプリと不動産の業務アプリで、同じ原因が起きた
この記事は、AI(Claude)の支援を受けて作成し、筆者が内容を確認しています。


