Skip to content
Development
Skill

/state-restoration

Generates state preservation and restoration infrastructure for navigation paths, tab selection, scroll positions, and form data across app launches and background termination. Use when user wants to save/restore app state, remember where the user left off, or persist UI state.

From plugin
rshankras-apple-skills
848181 skills

Claude Code

$ npx -y skills add rshankras/claude-code-apple-skills --skill state-restoration --agent claude-code

SKILL.md

state-restoration.SKILL.md
name: state-restoration
description: Generates state preservation and restoration infrastructure for navigation paths, tab selection, scroll positions, and form data across app launches and background termination. Use when user wants to save/restore app state, remember where the user left off, or persist UI state.
allowed-tools: [Read, Write, Edit, Glob, Grep, Bash, AskUserQuestion]
last_verified: 2026-07-16
review_by: 2027-06-22
os_version: iOS 27 / macOS 27

State Restoration Generator

Generate production state restoration infrastructure that saves and restores app state (selected tab, scroll position, navigation path, form data) across launches and background termination. Uses Codable state models, @SceneStorage, @AppStorage, and custom file-based persistence.

When This Skill Activates

Use this skill when the user:

  • Asks to "add state restoration" or "restore state"
  • Wants to "save app state" or "persist UI state"
  • Mentions "preserve navigation" or "remember navigation path"
  • Asks to "remember scroll position" or "restore scroll position"
  • Wants the app to "resume where left off" or "remember where I was"
  • Asks about "saving form drafts" or "preserve form data"
  • Mentions "tab selection persistence" or "remember selected tab"

Pre-Generation Checks

1. Project Context Detection

  • [ ] Check Swift version (requires Swift 5.9+)
  • [ ] Check deployment target (iOS 17+ / macOS 14+ for @Observable)
  • [ ] Check for existing state saving code
  • [ ] Identify source file locations

2. Conflict Detection

Search for existing state restoration:

Glob: **/*StateRestoration*.swift, **/*AppState*.swift, **/*SceneStorage*.swift
Grep: "SceneStorage" or "NavigationPath" or "selectedTab" or "scrollPosition"

If existing state management found:

  • Ask if user wants to replace or extend it
  • If extending, integrate with the existing approach

3. Navigation Pattern Detection

Determine which navigation pattern the app uses:

Grep: "NavigationStack" or "NavigationSplitView" or "TabView" or "NavigationLink"

This affects which restoration components to generate.

Configuration Questions

Ask user via AskUserQuestion:

1. **What state to restore?** (multi-select)

  • Navigation path (back stack, detail selection)
  • Selected tab (TabView selection)
  • Scroll position (list/scroll view offset)
  • Form data (unsaved drafts and input fields)
  • All of the above — recommended

2. **Storage method?**

  • @SceneStorage / @AppStorage (simple, per-scene, limited to basic types)
  • UserDefaults (shared across scenes, limited size)
  • File-based (Codable to JSON file in Application Support — recommended for complex state)

3. **Restore behavior?**

  • Always restore (seamless resume on every launch)
  • Time-limited (restore only if last session was within N minutes) — recommended
  • Ask user (show "Resume where you left off?" prompt)

Generation Process

Step 1: Read Templates

Read `templates.md` for production Swift code.

Step 2: Create Core Files

Generate these files: 1. `AppState.swift` — Codable struct capturing all restorable state 2. `StateRestorationManager.swift` — @Observable manager with auto-save and restore

Step 3: Create Feature Files

Based on configuration: 3. `NavigationStateModifier.swift` — If navigation path selected 4. `ScrollRestorationModifier.swift` — If scroll position selected 5. `TabRestorationModifier.swift` — If tab selection selected 6. `FormDraftManager.swift` — If form data selected

Step 4: Determine File Location

Check project structure:

  • If `Sources/` exists -> `Sources/StateRestoration/`
  • If `App/` exists -> `App/StateRestoration/`
  • Otherwise -> `StateRestoration/`

Output Format

After generation, provide:

Files Created

StateRestoration/
├── AppState.swift                  # Codable state model
├── StateRestorationManager.swift   # Auto-save/restore orchestrator
├── NavigationStateModifier.swift   # Navigation path persistence (optional)
├── ScrollRestorationModifier.swift # Scroll position persistence (optional)
├── TabRestorationModifier.swift    # Tab selection persistence (optional)
└── FormDraftManager.swift          # Form draft auto-save (optional)

Integration Steps

**Basic setup in App struct:**

@main
struct MyApp: App {
    @State private var stateManager = StateRestorationManager()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(stateManager)
        }
    }
}

**Restore navigation path:**

struct ContentView: View {
    @Environment(StateRestorationManager.self) private var stateManager

    var body: some View {
        @Bindable var sm = stateManager
        NavigationStack(path: $sm.navigationPath) {
            HomeView()
                .navigationDestination(for: Route.self) { route in
                    RouteView(route: route)
                }
        }
        .modifier(NavigationStateModifier(stateManager: stateManager))
    }
}

**Restore tab selection:**

struct MainTabView: View {
    @Environment(StateRestorationManager.self) private var stateManager

    var body: some View {
        @Bindable var sm = stateManager
        TabView(selection: $sm.selectedTab) {
            HomeTab().tag(0)
            SearchTab().tag(1)
            ProfileTab().tag(2)
        }
        .modifier(TabRestorationModifier(stateManager: stateManager))
    }
}

**Restore scroll position:**

struct ItemListView: View {
    let items: [Item]

    var body: some View {
        ScrollView {
            LazyVStack {
                ForEach(items) { item in
                    ItemRow(item: item)
                }
            }
        }
        .modifier(ScrollRestorationModifier(scrollViewID: "item-list"))
    }
}

**Auto-save form drafts:**

struct ComposeView: View {
    @State private var draftManager = FormDraftManager(formID: "compose")
    @State private
Read more
@rshankras
Ships withrshankras-apple-skills

A collection of Claude Code skills for iOS, macOS, watchOS, visionOS, and Apple platform development. These skills help you plan and build apps, maintain code quality, ensure HIG compliance, and guide you from idea to App Store.

Stars on GitHub

Momentum

stars in total
848
Star history of rshankras/claude-code-apple-skills on GitHub, a chart by star-history.com

Other skills on rshankras-apple-skills.

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills10d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc12d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react1d252k
@facebook@facebookInstall Skill

Questions about state-restoration.

Which coding agents can use state-restoration?
state-restoration installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.