swiftui-ui-patterns について
SwiftUI の画面や再利用可能なコンポーネントを作成・改修する開発者向けのリファレンススキルです。状態の所有、ネイティブなデータフロー、ナビゲーション、非同期 UI、ビルド検証を扱います。
主な機能
- 01SwiftUI の状態所有に関する指針
- 02ナビゲーションとシートのパターン
- 03非同期の読み込みとエラー状態
- 04再利用可能なコンポーネント構成
- 05プレビューとビルド検証の手順
活用シーン
- 01新しい SwiftUI 画面の実装
- 02既存ビューのリファクタリング
- 03アプリのナビゲーションとシートの構築
- 04画面の非同期状態の処理
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ sickn33/ agentic-awesome-skills --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 パターン
クイックスタート
使用する場面
- 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、シート) に基づいて、次のコンポーネントリファレンスを選びます。
- 新しい画面が追加されるたびに、ルートとシートの enum を拡張します。
従うべき一般的なルール
- モダンな 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 を明記します。
- 既存のレガシーパターンは、レガシーファイルを編集する場合にのみ維持します。
- プロジェクトのフォーマッターとスタイルガイドに従います。
- シート: 状態が選択されたモデルを表す場合は、
.sheet(isPresented:)よりも.sheet(item:)を優先します。シートの body 内でif letを避けます。シートは自身のアクションを所有し、onCancel/onConfirmクロージャを転送するのではなく、内部でdismiss()を呼び出すべきです。 - スクロール駆動の表示: スクロールオフセットから正規化された進捗値を導出し、その単一の信頼できる情報源から視覚状態を駆動することを優先します。スクロールだけではインタラクションを表現できない場合を除き、並行するジェスチャー状態マシンを避けます。
状態の所有権のまとめ
所有権モデルに一致する最も狭い状態ツールを使用してください:
| シナリオ | 推奨パターン |
|---|---|
| 1 つのビューが所有するローカル UI 状態 | @State |
| 子が親所有の値状態を変更する | @Binding |
| iOS 17+ でルートが所有する参照モデル | @Observable 型を伴う @State |
iOS 17+ で子が注入された @Observable モデルを読み取りまたは変更する | ストアドプロパティとして明示的に渡す |
| 共有アプリサービスまたは構成 | @Environment(Type.self) |
| iOS 16 以前のレガシー参照モデル | ルートで @StateObject、注入時は @ObservedObject |
まず所有権の位置を選び、次にラッパーを選択します。単純な値状態で十分な場合は、参照モデルを導入しないでください。
横断的な参照
references/navigationstack.md: ナビゲーションの所有権、タブごとの履歴、enum によるルーティング。references/sheets.md: 集中的なモーダル表示と enum 駆動のシート。references/deeplinks.md: URL の処理と、外部リンクをアプリ内の遷移先へルーティングする方法。references/app-wiring.md: ルートの依存関係グラフ、environment の使用法、アプリシェルの配線。references/async-state.md:.task、.task(id:)、キャンセル、デバウンス、非同期 UI の状態。references/previews.md:#Preview、フィクスチャ、モック環境、分離されたプレビュー設定。references/performance.md: 安定した identity、observation のスコープ、遅延コンテナ、レンダリングコストのガードレール。
アンチパターン
- レイアウト、ビジネスロジック、ネットワーキング、ルーティング、フォーマットを 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を読みます。 - ビルドで検証します。コンパイラエラーがないことを確認し、プレビューがクラッシュせずにレンダリングされることを確認し、状態の変化が正しく伝播することを確認し、リストの identity と observation のスコープが回避可能な再レンダリングを引き起こさないことを確認します。画面が大きく、スクロールが多く、または頻繁に更新される場合は、
references/performance.mdを読みます。よくある SwiftUI のコンパイルエラー —@Stateアノテーションの欠落、曖昧なViewBuilderクロージャ、一致しないジェネリック型 — は、呼び出し箇所を更新する前に解決します。ビルドが失敗した場合: エラーメッセージを注意深く読み、特定された問題を修正し、次のステップに進む前に再ビルドします。プレビューがクラッシュした場合は、問題のあるサブビューを切り分け、その状態の初期化が有効であることを確認し、続行する前にプレビューを再実行します。
コンポーネント参照
references/components-index.md をエントリーポイントとして使用します。各コンポーネント参照には次を含める必要があります:
- 意図と最適なシナリオ。
- ローカル規約を用いた最小限の使用パターン。
- 落とし穴とパフォーマンスに関する注意。
- 現在のリポジトリ内の既存の例へのパス。
新しいコンポーネント参照の追加
references/<component>.mdを作成します。- 短く実行可能に保ち、現在のリポジトリ内の具体的なファイルにリンクします。
references/components-index.mdを新しいエントリーで更新します。
制限事項
- このスキルは、タスクが上記で説明されたスコープに明確に一致する場合にのみ使用します。
- 出力を、環境固有の検証、テスト、または専門家によるレビューの代わりとして扱わないでください。
- 必要な入力、権限、安全境界、または成功基準が欠けている場合は、停止して明確化を求めます。
コメント
Markdown 対応