Back to Skills

mvvm-architecture

verified

Expert MVVM decisions for iOS/tvOS: choosing between ViewModel patterns (state enum vs published properties vs Combine), service layer boundaries, dependency injection strategies, and testing approaches. Use when designing ViewModel architecture, debugging data flow issues, or deciding where business logic belongs. Trigger keywords: MVVM, ViewModel, ObservableObject, @StateObject, service layer, dependency injection, unit test, mock, architecture

View on GitHub

Marketplace

manifest-marketplace

Kaakati/rails-enterprise-dev

Plugin

reactree-ios-dev

development

Repository

Kaakati/rails-enterprise-dev
2stars

plugins/reactree-ios-dev/skills/mvvm-architecture/SKILL.md

Last Verified

January 25, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/Kaakati/rails-enterprise-dev/blob/main/plugins/reactree-ios-dev/skills/mvvm-architecture/SKILL.md -a claude-code --skill mvvm-architecture

Installation paths:

Claude
.claude/skills/mvvm-architecture/
Powered by add-skill CLI

Instructions

# MVVM Architecture — Expert Decisions

Expert decision frameworks for MVVM choices in iOS/tvOS. Claude knows MVVM basics — this skill provides judgment calls for non-obvious decisions.

---

## Decision Trees

### ViewModel Pattern Selection

```
Does the screen have distinct, mutually exclusive states?
├─ YES (loading → loaded → error)
│  └─ State Enum Pattern
│     @Published var state: State = .idle
│     enum State { case idle, loading, loaded(Data), error(String) }
│
└─ NO (multiple independent properties)
   └─ Does the screen need form validation?
      ├─ YES → Combine Pattern (publishers for validation chains)
      └─ NO → Published Properties Pattern (simplest)
```

**When State Enum wins**: Product detail (loading → product → error), authentication flows, wizard steps. Forces exhaustive handling.

**When Published Properties win**: Dashboard with multiple independent sections that load/fail independently. State enum becomes unwieldy with 2^n combinations.

### Where Does Logic Belong?

```
Is it data transformation for display?
├─ YES → ViewModel (formatting, filtering visible data)
│
└─ NO → Is it reusable business logic?
   ├─ YES → Service Layer (API calls, validation rules, caching)
   │
   └─ NO → Is it pure domain logic?
      ├─ YES → Model (computed properties, domain rules)
      └─ NO → Reconsider if it's needed
```

**The trap**: Putting API calls directly in ViewModel. Makes testing require network mocking instead of simple service mocking.

### @StateObject Injection

```
Does ViewModel need dependencies from parent?
├─ NO → Direct initialization
│  @StateObject private var viewModel = UserViewModel()
│
└─ YES → How many dependencies?
   ├─ 1-2 → Init parameter
   │  init(userId: String) {
   │      _viewModel = StateObject(wrappedValue: UserViewModel(userId: userId))
   │  }
   │
   └─ Many → Factory/Container
      @StateObject private var viewModel: UserViewModel
      init() {
          _viewModel = StateObject(wrappedValue: Container.s

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
9342 chars