smithery.ai

screen-architecture

iOS画面実?

First seen Apr 28, 2026

Installation

$ npx skills add https://smithery.ai

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 8,626 B
  • docs SUMMARY.md 615 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

Screen Architecture

Reduxパターンによる画面実装の設計指針。

Reduxパターンとは

JavaScriptエコシステムで生まれた状態管理パターン。3つの原則に基づく:

  1. Single Source of Truth: アプリ全体の状態は単一のStoreに保持
  2. State is Read-Only: 状態変更はActionを発行することでのみ行う
  3. Changes with Pure Functions: Reducerは純粋関数

iOSではTCA (The Composable Architecture) が有名だが、このスキルではTCAを使わずに同じ思想を実現する。

設計思想

  1. Single Root State: 状態はルートで一元管理。子ビューは必要な値を親から受け取る
  2. Reducerでロジック分離: ビジネスロジックは純粋関数として切り出し、テスト可能に
  3. SwiftUIに任せる: 画面更新のタイミングやパフォーマンスはSwiftUIの差分更新に委ねる

基本構造

App/
├── AppState.swift           # ルート状態(Single Source of Truth)
├── AppAction.swift          # 全アクション定義
├── AppStore.swift           # Store(状態保持 + Action dispatch)
├── Features/
│   ├── Order/
│   │   ├── OrderState.swift     # 機能別の状態(AppStateの一部)
│   │   ├── OrderAction.swift    # 機能別のアクション
│   │   ├── OrderReducer.swift   # 純粋関数(テスト対象)
│   │   └── OrderView.swift      # View(パラメータを受け取るだけ)
│   └── Profile/
│       └── ...
└── Services/                # 副作用(API、DB等)
    └── OrderService.swift

State

AppState(ルート)

struct AppState {
    var order = OrderState()
    var profile = ProfileState()
    var navigation = NavigationState()
}

Feature State

struct OrderState {
    var orders: [Order] = []
    var isLoading = false
    var error: Error?
}

状態は値型(struct)で定義。AppStateが唯一の真実の源。

Action

enum AppAction {
    case order(OrderAction)
    case profile(ProfileAction)
}

enum OrderAction {
    case loadOrders
    case ordersLoaded([Order])
    case ordersFailed(Error)
    case selectOrder(Order)
}

Reducer

ビジネスロジックを純粋関数として定義。テストの主要対象。

enum OrderReducer {
    static func reduce(state: inout OrderState, action: OrderAction) {
        switch action {
        case .loadOrders:
            state.isLoading = true
            state.error = nil

        case .ordersLoaded(let orders):
            state.orders = orders
            state.isLoading = false

        case .ordersFailed(let error):
            state.error = error
            state.isLoading = false

        case .selectOrder(let order):
            // 選択状態の更新など
            break
        }
    }
}

AppReducer(統合)

enum AppReducer {
    static func reduce(state: inout AppState, action: AppAction) {
        switch action {
        case .order(let action):
            OrderReducer.reduce(state: &state.order, action: action)
        case .profile(let action):
            ProfileReducer.reduce(state: &state.profile, action: action)
        }
    }
}

Store

状態の保持とAction dispatchを担当。副作用(API呼び出し等)もここで処理。

@MainActor
final class AppStore: ObservableObject {
    @Published private(set) var state = AppState()

    // Dependencies
    private let orderService: OrderServiceProtocol

    init(orderService: OrderServiceProtocol) {
        self.orderService = orderService
    }

    func send(_ action: AppAction) {
        // 1. Reducerで状態更新
        AppReducer.reduce(state: &state, action: action)

        // 2. 副作用の実行
        Task {
            await handleSideEffects(action)
        }
    }

    private func handleSideEffects(_ action: AppAction) async {
        switch action {
        case .order(.loadOrders):
            do {
                let orders = try await orderService.fetchOrders()
                send(.order(.ordersLoaded(orders)))
            } catch {
                send(.order(.ordersFailed(error)))
            }

        default:
            break
        }
    }
}

View

Viewはパラメータを受け取り、表示とアクション送信のみを担当。

RootView

@main
struct MyApp: App {
    @StateObject private var store = AppStore(
        orderService: OrderService()
    )

    var body: some Scene {
        WindowGroup {
            RootView()
                .environmentObject(store)
        }
    }
}

Feature View

struct OrderListView: View {
    // 必要な値だけを受け取る
    let orders: [Order]
    let isLoading: Bool
    let onOrderTap: (Order) -> Void
    let onRefresh: () -> Void

    var body: some View {
        Group {
            if isLoading {
                ProgressView()
            } else {
                List(orders) { order in
                    OrderRow(order: order)
                        .onTapGesture { onOrderTap(order) }
                }
                .refreshable { onRefresh() }
            }
        }
    }
}

// 親から呼び出す
struct OrderContainerView: View {
    @EnvironmentObject var store: AppStore

    var body: some View {
        OrderListView(
            orders: store.state.order.orders,
            isLoading: store.state.order.isLoading,
            onOrderTap: { store.send(.order(.selectOrder($0))) },
            onRefresh: { store.send(.order(.loadOrders)) }
        )
    }
}

なぜこの形式か

  • OrderListViewは純粋なView: 状態を持たず、渡された値を表示するだけ。Preview可能
  • OrderContainerView: Storeとの橋渡し。状態の購読とアクション送信
  • SwiftUIに任せる: store.state.order.ordersが変わればSwiftUIが自動で差分更新

プロトタイプ→本番実装ワークフロー

1. 状態の抽出

プロトタイプ内の@StateをFeature Stateに移動:

// Before(プロトタイプ)
struct OrderView: View {
    @State private var orders: [Order] = []
    @State private var isLoading = false
}

// After(Feature State)
struct OrderState {
    var orders: [Order] = []
    var isLoading = false
}

2. アクションの定義

ユーザー操作とイベントをAction enumに。非同期結果も含める:

enum OrderAction {
    // ユーザー操作
    case loadOrders
    case selectOrder(Order)

    // 非同期結果
    case ordersLoaded([Order])
    case ordersFailed(Error)
}

3. Reducerの作成

状態更新ロジックを純粋関数に:

enum OrderReducer {
    static func reduce(state: inout OrderState, action: OrderAction) {
        // 同期的な状態更新のみ
    }
}

4. 副作用の実装

Storeで非同期処理を実行:

private func handleSideEffects(_ action: AppAction) async {
    // API呼び出しなど
}

5. Viewの簡素化

Viewをパラメータ受け取り形式に変換。

6. テストの追加

Reducerのテストを作成(純粋関数なのでテストしやすい)。

チェックリスト

  • 状態はAppState配下で一元管理されているか
  • 子Viewは@Stateを持たず、パラメータを受け取っているか
  • ビジネスロジックはReducerに切り出されているか
  • Reducerは純粋関数か(副作用なし)
  • 副作用(API等)はStoreで処理されているか
  • Reducerのテストが作成されているか

リファレンス

ファイル 内容
references/state-management.md 状態設計の詳細パターン
references/testing-guide.md Reducerテストの書き方