---
name: ios-swiftui-architect
description: "Design SwiftUI apps with clean architecture: MV pattern, @Observable, and Swift Concurrency. Plans your SwiftUI screen hierarchy, writes async/await data layers, and reviews Xcode build settings for App Store submission."
license: MIT
---

# iOS SwiftUI Architect

A planning-and-review companion for SwiftUI engineers who want screens that stay testable as the app grows. It leans on the MV (Model-View) pattern with Apple's `@Observable` macro and structured concurrency, rather than wrapping every view in a heavyweight view-model. Aimed at developers building iOS 17+ apps who keep ending up with massive views, callback soup, or `@Published` chains they can no longer reason about.

## When to use it

- You're starting a new feature and want the view hierarchy, navigation, and data flow sketched before you write code.
- An existing screen mixes networking, formatting, and layout, and you need a refactor plan.
- You're migrating off `ObservableObject` / `@Published` to the `@Observable` macro and want to know which `@StateObject`/`@ObservedObject` sites become `@State`/`@Bindable`.
- You're prepping an archive build and hit signing, bitcode, or `Info.plist` capability errors.

## What it does

- **Screen planning** — proposes a tree of views with `NavigationStack`, value-based `navigationDestination(for:)`, and where to lift state vs. pass `@Binding`.
- **Concurrency-first data layer** — writes `async`/`await` repositories and services, models endpoints with `URLSession.shared.data(for:)`, isolates mutable state with `actor`, and marks UI-facing types `@MainActor`. It flags data races the Swift 6 strict-concurrency checker would reject and suggests `Sendable` conformances.
- **State design** — applies `@Observable` model objects held by views via `@State`, exposed downstream with `@Bindable`. Uses `.task(id:)` for lifecycle-bound loads and `.refreshable` for pull-to-refresh.
- **Build review** — inspects scheme settings, `SWIFT_STRICT_CONCURRENCY`, deployment target, and the archive/`xcodebuild` flow for App Store submission, including export options and common code-signing failures.

## Example

```bash
curl -fsSL --create-dirs -o ~/.claude/skills/ios-swiftui-architect/SKILL.md https://claudeskil.com/skills/ios-swiftui-architect/SKILL.md

# Then, in your project:
claude "Plan the screen hierarchy for a podcast app: list -> episode detail -> player.
Use @Observable, NavigationStack, and an async repository backed by URLSession."
```

A sketch it might produce:

```swift
@Observable final class EpisodeStore {
    private(set) var episodes: [Episode] = []
    private let repo: EpisodeRepository
    init(repo: EpisodeRepository) { self.repo = repo }
    func load() async throws { episodes = try await repo.fetch() }
}

struct EpisodeListView: View {
    @State private var store = EpisodeStore(repo: .live)
    var body: some View {
        NavigationStack {
            List(store.episodes) { ep in
                NavigationLink(ep.title, value: ep)
            }
            .navigationDestination(for: Episode.self, destination: EpisodeDetailView.init)
            .task { try? await store.load() }
        }
    }
}
```

## Tips & gotchas

- `@Observable` only tracks properties actually read in `body`; an unread property won't trigger redraws, which is a feature, not a bug.
- Don't reach for `@StateObject` with `@Observable` types — use `@State`. The macro replaces `ObservableObject` entirely.
- Keep `actor`-isolated work off the main thread, but hop back with `@MainActor` before mutating view state, or you'll see purple runtime warnings.
- `.task` cancels automatically when the view disappears; long uploads belong in a detached task or background session instead.

## FAQ

**Does it require iOS 17?** The `@Observable` macro and value-based `navigationDestination` need iOS 17 / Xcode 15+. For older targets it falls back to `ObservableObject` plans.

**Does it write tests?** It structures code for testability (protocol-based repositories, injectable stores) and can scaffold `XCTest`/Swift Testing cases, but it does not run them.

**Can it open Xcode for me?** No — it reviews settings and emits `xcodebuild` commands; you run the build.
