Agent Skills by ALSEL
Anthropic ClaudeLLM・AI開発⭐ リポ 0品質スコア 50/100

swiftui-view-refactor

SwiftUIのViewファイルをリファクタリング・レビューするスキルです。小さな専用サブビューへの分割、MV(Model-View)アーキテクチャによるデータフロー、安定したViewツリーの構築、明示的な依存性注入、正しいObservationの使い方を基本方針としています。Viewの整理、長い`body`の分割、インラインアクションや副作用の除去、`some View`を返すcomputed helperの削減、`@Observable`やViewModelの初期化パターンの標準化を行いたいときに使用してください。

description の原文を見る

Refactor and review SwiftUI view files with strong defaults for small dedicated subviews, MV-over-MVVM data flow, stable view trees, explicit dependency injection, and correct Observation usage. Use when cleaning up a SwiftUI view, splitting long bodies, removing inline actions or side effects, reducing computed `some View` helpers, or standardizing `@Observable` and view model initialization patterns.

SKILL.md 本文

SwiftUI View Refactor

Overview

SwiftUI ビューを小規模で明示的で安定した View 型へリファクタリングします。デフォルトは vanilla SwiftUI を使用:ローカル状態はビューに、共有依存関係は environment に、ビジネスロジックはサービス/モデルに、ビューモデルはリクエストまたは既存コードが明確に要求する場合のみ使用します。

Core Guidelines

1) View の順序 (上 → 下)

  • 既存ファイルがより強いローカル規約を持つ場合を除き、この順序を適用してください。
  • Environment
  • private/public let
  • @State / その他のストアドプロパティ
  • computed var (ビュー以外)
  • init
  • body
  • computed view builders / その他のビューヘルパー
  • ヘルパー / async 関数

2) デフォルトは MV、MVVM ではない

  • ビューは軽量な状態表現とオーケストレーションポイントであるべきで、ビジネスロジックのコンテナではありません。
  • ビューモデルに手を出す前に、@State@Environment@Query.task.task(id:)onChange を優先的に使用してください。
  • サービスと共有モデルを @Environment 経由でインジェクトし、ドメインロジックをビュー本体ではなくサービス/モデルに保ちます。
  • ローカルビューの状態をミラーリングしたり、environment の依存関係をラップするだけのためにビューモデルを導入しないでください。
  • 画面が大きくなっている場合は、新しいビューモデルレイヤーを発明する前に、UI を小規模なサブビューに分割してください。

3) computed some View ヘルパーより専用サブビュー型を強く優先

  • 約 1 画面よりも長いか、複数の論理的なセクションを含む body プロパティにフラグを立ててください。
  • 非自明なセクション、特に状態、async 作業、分岐を持つか、独自のプレビューがあるセクションについては、専用の View 型の抽出を優先します。
  • computed some View ヘルパーは稀で小規模に保ってください。private var header: some View スタイルのフラグメントで画面全体を構築しないでください。
  • 親の全状態を渡すのではなく、小規模で明示的な入力(データ、バインディング、コールバック)を抽出されたサブビューに渡します。
  • 抽出されたサブビューが再利用可能または独立して意味のあるものになった場合は、独自のファイルに移動してください。

優先する例:

var body: some View {
    List {
        HeaderSection(title: title, subtitle: subtitle)
        FilterSection(
            filterOptions: filterOptions,
            selectedFilter: $selectedFilter
        )
        ResultsSection(items: filteredItems)
        FooterSection()
    }
}

private struct HeaderSection: View {
    let title: String
    let subtitle: String

    var body: some View {
        VStack(alignment: .leading, spacing: 6) {
            Text(title).font(.title2)
            Text(subtitle).font(.subheadline)
        }
    }
}

private struct FilterSection: View {
    let filterOptions: [FilterOption]
    @Binding var selectedFilter: FilterOption

    var body: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack {
                ForEach(filterOptions, id: \.self) { option in
                    FilterChip(option: option, isSelected: option == selectedFilter)
                        .onTapGesture { selectedFilter = option }
                }
            }
        }
    }
}

避ける例:

var body: some View {
    List {
        header
        filters
        results
        footer
    }
}

private var header: some View {
    VStack(alignment: .leading, spacing: 6) {
        Text(title).font(.title2)
        Text(subtitle).font(.subheadline)
    }
}

3b) body からアクションとサイドエフェクトを抽出

  • 非自明なボタンアクションをビュー本体にインラインで保たないでください。
  • ビジネスロジックを .task.onAppear.onChange.refreshable に埋め込まないでください。
  • ビューから小規模なプライベートメソッドを呼び出すことを優先し、実際のビジネスロジックをサービス/モデルに移動してください。
  • 本体はビューコントローラーのようではなく、UI のように読まれるべきです。
Button("Save", action: save)
    .disabled(isSaving)

.task(id: searchText) {
    await reload(for: searchText)
}

private func save() {
    Task { await saveAsync() }
}

private func reload(for searchText: String) async {
    guard !searchText.isEmpty else {
        results = []
        return
    }
    await searchService.search(searchText)
}

4) 安定したビュー木を保つ (トップレベルの条件付きビュー交換を避ける)

  • if/else 経由で完全に異なるルートブランチを返す body または computed ビューを避けてください。
  • 条件をセクション/修飾子内に置いた単一の安定した基本ビューを優先します (overlayopacitydisabledtoolbar など)。
  • ルートレベルのブランチ交換は ID チャーンを引き起こし、より広い無効化とさらなる再計算を招きます。

優先する例:

var body: some View {
    List {
        documentsListContent
    }
    .toolbar {
        if canEdit {
            editToolbar
        }
    }
}

避ける例:

var documentsListView: some View {
    if canEdit {
        editableDocumentsList
    } else {
        readOnlyDocumentsList
    }
}

5) ビューモデルの処理 (既に存在するか明示的にリクエストされた場合のみ)

  • ビューモデルをデフォルトではなく、レガシーまたは明示的な必要性パターンとして扱ってください。
  • リクエストまたは既存コードが明確に要求しない限り、ビューモデルを導入しないでください。
  • ビューモデルが存在する場合は、可能な限りそれを非オプショナルにしてください。
  • init 経由でビューに依存関係を渡し、ビューの init でビューモデルを作成してください。
  • bootstrapIfNeeded パターンおよび他の遅延セットアップ回避策を避けてください。

例(Observation ベース):

@State private var viewModel: SomeViewModel

init(dependency: Dependency) {
    _viewModel = State(initialValue: SomeViewModel(dependency: dependency))
}

6) Observation の使用

  • iOS 17+ の @Observable 参照型については、所有ビューに @State として保存してください。
  • observables を明示的に下に渡してください。UI が本当に必要としない限りオプショナル状態を避けてください。
  • デプロイメントターゲットが iOS 16 以前を含む場合は、所有者で @StateObject を、レガシー observable モデルをインジェクトするときに @ObservedObject を使用してください。

Workflow

  1. ビューを順序付けルールに合わせて並び替えます。
  2. body からインラインアクションとサイドエフェクトを削除します。ビジネスロジックをサービス/モデルに移動し、ビューには薄いオーケストレーションのみを保ちます。
  3. 専用サブビュー型を抽出して長い本体を短縮します。多くの computed some View ヘルパーで画面を再構築しないでください。
  4. 安定したビュー構造を確保します。トップレベルの if ベースのブランチ交換を避け、条件をローカライズされたセクション/修飾子に移動してください。
  5. ビューモデルが存在するか明示的に必要な場合、オプショナルビューモデルを init で初期化されたノンオプショナル @State ビューモデルに置き換えてください。
  6. Observation の使用を確認します。iOS 17+ ではルート @Observable モデル向けに @State を、デプロイメントターゲットが必要とする場合のみレガシーラッパーを使用します。
  7. 動作を維持します。リクエストされない限り、レイアウトまたはビジネスロジックを変更しないでください。

Notes

  • 大規模な条件付きブロックおよび大規模な computed some View プロパティより小規模で明示的なビュー型を優先してください。
  • computed ビュー builders を body の下に、非ビュー computed vars を init の上に保ってください。
  • 優れた SwiftUI リファクタリングは、ビューが混合レイアウトと命令型ロジックではなく、データフローとレイアウトとして上から下へ読むようにします。
  • MV ファーストガイダンスと根拠については、references/mv-patterns.md を参照してください。

Large-view handling

SwiftUI ビューファイルが約 300 行を超える場合、積極的に分割します。複数の computed プロパティ内に複雑さを隠すのではなく、意味のあるセクションを専用の View 型に抽出します。アクションとヘルパー用の private 拡張と // MARK: - コメントを使用します。ただし、拡張を巨大な画面を小規模なビュー型に分割する代わりとして扱わないでください。抽出されたサブビューが再利用されるか、独立して意味のあるものの場合、独自のファイルに移動してください。

ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
dimillian
リポジトリ
dimillian/skills
ライセンス
MIT
最終更新
不明

Source: https://github.com/dimillian/skills / ライセンス: MIT

関連スキル

OpenAILLM・AI開発⭐ リポ 6,054

agent-browser

AI エージェント向けのブラウザ自動化 CLI です。ウェブサイトとの対話が必要な場合に使用します。ページ遷移、フォーム入力、ボタンクリック、スクリーンショット取得、データ抽出、ウェブアプリのテスト、ブラウザ操作の自動化など、あらゆるブラウザタスクに対応できます。「ウェブサイトを開く」「フォームに記入する」「ボタンをクリックする」「スクリーンショットを取得する」「ページからデータを抽出する」「このウェブアプリをテストする」「サイトにログインする」「ブラウザ操作を自動化する」といった要求や、プログラマティックなウェブ操作が必要なタスクで起動します。

by JimmyLv
汎用LLM・AI開発⭐ リポ 1,982

anyskill

AnySkill — あなたのプライベート・スキルクラウド。GitHubを基盤としたリポジトリからエージェントスキルを管理、同期、動的にロードできます。自然言語でクラウドスキルを検索し、オンデマンドでプロンプトを自動ロード、カスタムスキルのアップロードと共有、スキルバンドルの一括インストールが可能です。OpenClaw、Antigravity、Claude Code、Cursorに対応しています。

by LeoYeAI
汎用LLM・AI開発⭐ リポ 1,982

engram

AIエージェント向けの永続的なメモリシステムです。バグ修正、意思決定、発見、設定変更の後はmem_saveを使用してください。ユーザーが「覚えている」「記憶している」と言及した場合、または以前のセッションと重複する作業を開始する際はmem_searchを使用します。セッション終了前にmem_session_summaryを使用して、コンテキストを保持してください。

by LeoYeAI
汎用LLM・AI開発⭐ リポ 21,584

skyvern

AI駆動のブラウザ自動化により、任意のウェブサイトを自動化できます。フォーム入力、データ抽出、ファイルダウンロード、ログイン、複数ステップのワークフロー実行など、ユーザーがウェブサイトと連携する必要があるときに使用します。Skyvernは、LLMとコンピュータビジョンを活用して、未知のサイトも自動操作可能です。Python SDK、TypeScript SDK、REST API、MCPサーバー、またはCLIを通じて統合できます。

by Skyvern-AI
汎用LLM・AI開発⭐ リポ 1,149

pinchbench

PinchBenchベンチマークを実行して、OpenClawエージェントの実世界タスクにおけるパフォーマンスを評価できます。モデルの機能テスト、モデル間の比較、ベンチマーク結果のリーダーボード提出、またはOpenClawのセットアップがカレンダー、メール、リサーチ、コーディング、複数ステップのワークフローにどの程度対応しているかを確認する際に使用します。

by pinchbench
汎用LLM・AI開発⭐ リポ 4,693

openui

OpenUIとOpenUI Langを使用してジェネレーティブUIアプリを構築できます。これらはLLM生成インターフェースのためのトークン効率的なオープン標準です。OpenUI、@openuidev、ジェネレーティブUI、LLMからのストリーミングUI、AI向けコンポーネントライブラリ、またはjson-render/A2UIの置き換えについて述べる際に使用します。スキャフォルディング、defineComponent、システムプロンプト、Renderer、およびOpenUI Lang出力のデバッグに対応しています。

by thesysdev
本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: dimillian · dimillian/skills · ライセンス: MIT