swiftui-ui-patterns について
既存または新規プロジェクトでSwiftUIの画面を構築するためのリファレンススキルです。状態管理、ナビゲーション、表示、非同期UI状態、ビュー構成、検証方法を扱います。
主な機能
- 01SwiftUIの状態所有に関する指針
- 02ナビゲーションとシートのパターン
- 03非同期読み込みとエラー状態
- 04再利用可能なビュー構成
- 05ビルド・プレビュー・性能の確認
活用シーン
- 01既存のSwiftUIアプリに画面を追加
- 02新規アプリのナビゲーションを構築
- 03非同期読み込みとエラーUIを実装
- 04状態管理とビュー構成をレビュー
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ openai/ plugins --skill swiftui-ui-patternsインストール後、Claude Code で/swiftui-ui-patternsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamlreferences/app-wiring.mdasync-state.mdcomponents-index.mdcontrols.mddeeplinks.mdfocus.mdform.mdgrids.mdhaptics.mdinput-toolbar.mdlightweight-clients.mdlist.mdloading-placeholders.mdmacos-settings.mdmatched-transitions.mdmedia.mdmenu-bar.mdnavigationstack.mdoverlay.mdperformance.mdpreviews.mdscroll-reveal.mdscrollview.mdsearchable.mdsheets.mdsplit-views.mdtabview.mdtheming.mdtitle-menus.md詳細
SwiftUI UI パターン
クイックスタート
目標に合わせて、次のトラックを選択してください。
既存のプロジェクト
- 機能または画面と、主要なインタラクションモデル(リスト、詳細、エディター、設定、タブ)を特定します。
rg "TabView\("などを使ってリポジトリ内の近い例を探し、最も近い SwiftUI ビューを読みます。- ローカルの規約を適用します。SwiftUI ネイティブの状態管理を優先し、可能な限り状態をローカルに保ち、共有依存関係には環境への注入を使用します。
references/components-index.mdから関連するコンポーネントリファレンスを選び、その指針に従います。- プライマリコンテンツをドラッグまたはスクロールで移動するとセカンダリコンテンツが表示されるインタラクションの場合は、ジェスチャーを手動で実装する前に
references/scroll-reveal.mdを読みます。 - 小さく、役割を絞ったサブビューと SwiftUI ネイティブのデータフローを使ってビューを構築します。
新規プロジェクトのスキャフォールディング
references/app-wiring.mdから始めて、TabView + NavigationStack + シートを接続します。- 提供されているスケルトンをもとに、最小限の
AppTabとRouterPathを追加します。 - まず必要な UI に応じて、次のコンポーネントリファレンス(TabView、NavigationStack、シート)を選びます。
- 画面を追加するたびに、ルートとシートの列挙型を拡張します。
従うべき一般的なルール
- 最新の SwiftUI 状態管理(
@State、@Binding、@Observable、@Environment)を使用し、不要なビューモデルは避けます。 - デプロイメントターゲットに iOS 16 以前が含まれ、iOS 17 で導入された Observation API を使用できない場合は、
ObservableObjectに切り替えます。ルートでの所有には@StateObject、注入されたオブジェクトの監視には@ObservedObject、本当にアプリレベルで共有する状態に限って@EnvironmentObjectを使用してください。 - コンポジションを優先し、ビューは小さく、役割を絞ります。
.taskと明示的な読み込み/エラー状態を使って async/await を使用します。再起動、キャンセル、デバウンスに関する指針はreferences/async-state.mdを参照してください。- 共有アプリサービスは
@Environmentに置きますが、機能内に限定された依存関係やモデルには、明示的なイニシャライザー注入を優先します。ルートの接続パターンについてはreferences/app-wiring.mdを参照してください。 - デプロイメントターゲットに適合する最新の SwiftUI API を優先し、パターンの使用に特定の OS が必要な場合は、最低 OS バージョンを明記します。
- レガシーファイルを編集する場合に限り、既存のレガシーパターンを維持します。
- プロジェクトのフォーマッターとスタイルガイドに従います。
- シート:状態が選択されたモデルを表す場合は、
.sheet(isPresented:)より.sheet(item:)を優先します。シートの本文内でif letを使用しないでください。シートは自身のアクションを管理し、onCancel/onConfirmクロージャーを転送するのではなく、内部でdismiss()を呼び出します。 - スクロールに応じた表示:スクロールオフセットから正規化された進捗値を導出し、その単一の信頼できる情報源から表示状態を制御する方法を優先します。スクロールだけではインタラクションを表現できない場合を除き、並行するジェスチャー状態機械は避けます。
状態の所有権の概要
所有権モデルに合った、最も範囲の狭い状態管理ツールを使用します。
| シナリオ | 推奨パターン |
|---|---|
| 1 つのビューが所有するローカル UI 状態 | @State |
| 子ビューが親の所有する値型状態を変更する | @Binding |
| iOS 17 以降でルートが所有する参照モデル | @Observable 型を使った @State |
iOS 17 以降で子ビューが注入された @Observable モデルを読み取る、または変更する | 保存プロパティとして明示的に渡す |
| 共有アプリサービスまたは設定 | @Environment(Type.self) |
| iOS 16 以前のレガシー参照モデル | ルートでは @StateObject、注入時は @ObservedObject |
まず所有権の場所を選び、次にラッパーを選びます。単純な値型状態で十分な場合に、参照モデルを導入しないでください。
横断的なリファレンス
- 以下のリファレンスに加えて、SwiftUI の API、利用可能状況、プラットフォームに関する指針が変更されている可能性がある場合は、ウェブ検索を使って最新の Apple Developer ドキュメントを参照してください。
references/navigationstack.md:ナビゲーションの所有権、タブごとの履歴、enum によるルーティング。references/sheets.md:モーダル表示の一元管理、enum に基づくシート。references/deeplinks.md:URL の処理と、外部リンクからアプリ内の遷移先へのルーティング。references/app-wiring.md:ルートの依存関係グラフ、環境の使用方法、アプリシェルの配線。references/async-state.md:.task、.task(id:)、キャンセル、デバウンス、非同期 UI の状態。references/previews.md:#Preview、フィクスチャ、モック環境、分離されたプレビューのセットアップ。references/performance.md:安定した ID、監視範囲、遅延コンテナー、描画コストのガードレール。
アンチパターン
- レイアウト、ビジネスロジック、ネットワーク処理、ルーティング、書式設定を 1 つのファイルに混在させた巨大なビュー。
- 相互に排他的なシート、アラート、ナビゲーション先に対して、複数のブール値フラグを使うこと。
- ビューのライフサイクルフックや注入されたモデル/サービスを使わず、
bodyによって駆動されるコードパスでサービスを直接呼び出すこと。 - より適切なコンポジションで解決すべき型の不一致を回避するために、安易に
AnyViewを使うこと。 - 明確な所有権上の理由がないまま、共有依存関係をすべて
@EnvironmentObjectやグローバルルーターにすること。
新しい SwiftUI ビューを作成するワークフロー
- UI コードを書く前に、ビューの状態、その所有場所、想定する最低 OS バージョンを定義します。
@Environmentに属する依存関係と、明示的なイニシャライザー入力として保持する依存関係を特定します。- ビュー階層、ルーティングモデル、表示箇所を大まかに設計し、繰り返し使う部分をサブビューに切り出します。複雑なナビゲーションについては、
references/navigationstack.md、references/sheets.md、またはreferences/deeplinks.mdを参照してください。次に進む前にビルドし、コンパイラーエラーがないことを確認してください。 - 必要に応じて明示的な読み込み状態とエラー状態を用意し、
.taskまたは.task(id:)で非同期読み込みを実装します。入力の変化やキャンセルが関わる場合は、references/async-state.mdを参照してください。 - 主要な状態と副次的な状態のプレビューを追加し、UI がインタラクティブな場合はアクセシビリティラベルまたは識別子を追加します。フィクスチャや注入されたモック依存関係が必要な場合は、
references/previews.mdを参照してください。 - ビルドして検証します。コンパイラーエラーがないこと、プレビューがクラッシュせずに描画されること、状態の変化が正しく伝播することを確認し、リストの ID と監視範囲によって回避可能な再描画が発生しないことを確認します。画面が大きい場合、スクロールが多い場合、または頻繁に更新される場合は、
references/performance.mdを参照してください。よくある SwiftUI のコンパイルエラー(@State注釈の不足、ViewBuilderクロージャーの曖昧さ、ジェネリック型の不一致など)は、呼び出し元を更新する前に解決してください。ビルドに失敗した場合: エラーメッセージを注意深く読み、特定された問題を修正してから、次のステップに進む前に再ビルドしてください。プレビューがクラッシュする場合は、問題のあるサブビューを切り分け、その状態の初期化が有効であることを確認してから、続行する前にプレビューを再実行してください。
コンポーネントのリファレンス
エントリーポイントとして references/components-index.md を使用してください。各コンポーネントのリファレンスには、以下を含めてください。
- 目的と、最適な使用シナリオ。
- ローカルの規約に沿った最小限の使用パターン。
- 注意点とパフォーマンスに関する注記。
- 現在のリポジトリ内にある既存の例へのパス。
新しいコンポーネントのリファレンスを追加する
references/<component>.mdを作成します。- 簡潔で実用的な内容にし、現在のリポジトリ内の具体的なファイルへのリンクを含めます。
references/components-index.mdに新しい項目を追加します。
コメント
Markdown 対応