Get the FREE Ultimate OpenClaw Setup Guide →

Swift & SwiftUI Expert

Scanned
npx machina-cli add skill ojowwalker77/Claude-Matrix/swift-swiftui --openclaw
Files (1)
SKILL.md
8.8 KB

Swift & SwiftUI Expert

Expert-level guidance for Swift and SwiftUI development with modern patterns, iOS 17+/macOS 14+ best practices, and production-ready code generation.

Core Principles

When writing Swift/SwiftUI code, ALWAYS follow these principles:

1. Modern State Management (iOS 17+)

Use @Observable macro instead of ObservableObject:

// MODERN (iOS 17+)
@Observable
class UserViewModel {
    var name: String = ""
    var isLoggedIn: Bool = false
}

// View owns the model
struct ContentView: View {
    @State private var viewModel = UserViewModel()
    var body: some View {
        Text(viewModel.name)
    }
}

// Child view (read-only) - NO wrapper needed
struct ProfileView: View {
    var viewModel: UserViewModel  // Just pass it
    var body: some View {
        Text(viewModel.name)
    }
}

// Child view (needs binding)
struct EditView: View {
    @Bindable var viewModel: UserViewModel
    var body: some View {
        TextField("Name", text: $viewModel.name)
    }
}

2. Property Wrapper Decision Tree

Use CaseProperty Wrapper
Local view state (value types)@State
Two-way binding to parent state@Binding
Observable model (view owns)@State + @Observable class
Observable model (read-only child)No wrapper (just pass object)
Observable model (needs binding)@Bindable
Shared app-wide state@Environment
User defaults@AppStorage
Scene storage@SceneStorage
Focus state@FocusState

3. Architecture Patterns

For most apps: Modern MVVM with @Observable For large apps with teams: TCA (Composable Architecture) For simple views: No ViewModel needed

See references/architecture.md for detailed patterns.

Anti-Patterns to AVOID

State Management

// WRONG: @ObservedObject with initialization
@ObservedObject var viewModel = ViewModel()  // Will crash!

// RIGHT: Use @StateObject or @State
@StateObject private var viewModel = ViewModel()  // Legacy
@State private var viewModel = ViewModel()  // Modern (iOS 17+)
// WRONG: @State with reference types
@State var user: User  // Where User is a class

// RIGHT: @State only for value types
@State var userName: String
@State private var viewModel = ViewModel()  // Only with @Observable
// WRONG: Clearing data on error
func refresh() async {
    self.items = []  // Data disappears if error occurs!
    do {
        self.items = try await fetchItems()
    } catch {
        // Items now empty forever
    }
}

// RIGHT: Preserve existing data
func refresh() async {
    do {
        self.items = try await fetchItems()
    } catch {
        // Keep existing items, show error toast
    }
}

Performance

// WRONG: Heavy computation in body
var body: some View {
    let sorted = items.sorted { ... }.filter { ... }  // Runs every render!
    List(sorted) { ... }
}

// RIGHT: Memoize or compute elsewhere
var sortedItems: [Item] {
    items.sorted { ... }.filter { ... }
}  // Or use @State for expensive computations
// WRONG: Using id modifier on lazy content
LazyVStack {
    ForEach(items) { item in
        ItemView(item: item)
            .id(item.id)  // Breaks lazy loading!
    }
}

// RIGHT: Let ForEach handle identity
LazyVStack {
    ForEach(items) { item in
        ItemView(item: item)  // ForEach uses Identifiable
    }
}

Navigation

// WRONG: Using deprecated NavigationView
NavigationView {
    List { ... }
}

// RIGHT: Use NavigationStack (iOS 16+)
NavigationStack {
    List { ... }
}

Code Generation Guidelines

When generating Swift/SwiftUI code:

  1. Target iOS 17+/macOS 14+ unless user specifies otherwise
  2. Use @Observable instead of ObservableObject/@Published
  3. Use NavigationStack instead of NavigationView
  4. Use .task instead of .onAppear for async work
  5. Use Swift concurrency (async/await) instead of Combine for new code
  6. Make @State private always
  7. Prefer value types (structs, enums) over classes
  8. Use optionals correctly - never force unwrap without safety
  9. Handle errors explicitly - use do-catch, not try?
  10. Add accessibility - labels, hints, traits

Reference Documents

For detailed guidance, consult:

  • references/state-management.md - Property wrappers, @Observable, data flow
  • references/architecture.md - MVVM, TCA, Clean Architecture patterns
  • references/navigation.md - NavigationStack, programmatic navigation, deep links
  • references/performance.md - Lazy views, List optimization, render cycles
  • references/concurrency.md - async/await, actors, MainActor, Task
  • references/testing.md - Unit tests, ViewInspector, UI tests
  • references/accessibility.md - VoiceOver, Dynamic Type, accessibility modifiers
  • references/swiftdata.md - @Model, @Query, persistence patterns
  • references/anti-patterns.md - Common mistakes and how to fix them

Examples

Basic View with State

struct CounterView: View {
    @State private var count = 0

    var body: some View {
        VStack(spacing: 20) {
            Text("Count: \(count)")
                .font(.largeTitle)

            Button("Increment") {
                count += 1
            }
            .buttonStyle(.borderedProminent)
        }
        .accessibilityElement(children: .combine)
        .accessibilityLabel("Counter at \(count)")
        .accessibilityHint("Double tap the button to increment")
    }
}

ViewModel with @Observable

@Observable
class TaskListViewModel {
    var tasks: [Task] = []
    var isLoading = false
    var errorMessage: String?

    @MainActor
    func loadTasks() async {
        isLoading = true
        defer { isLoading = false }

        do {
            tasks = try await TaskService.shared.fetchTasks()
        } catch {
            errorMessage = error.localizedDescription
        }
    }
}

struct TaskListView: View {
    @State private var viewModel = TaskListViewModel()

    var body: some View {
        NavigationStack {
            Group {
                if viewModel.isLoading {
                    ProgressView()
                } else {
                    List(viewModel.tasks) { task in
                        TaskRow(task: task)
                    }
                }
            }
            .navigationTitle("Tasks")
        }
        .task {
            await viewModel.loadTasks()
        }
    }
}

Navigation with Type-Safe Routes

enum Route: Hashable {
    case detail(Item)
    case settings
    case profile(userId: String)
}

struct ContentView: View {
    @State private var path = NavigationPath()

    var body: some View {
        NavigationStack(path: $path) {
            List(items) { item in
                Button(item.name) {
                    path.append(Route.detail(item))
                }
            }
            .navigationDestination(for: Route.self) { route in
                switch route {
                case .detail(let item):
                    DetailView(item: item)
                case .settings:
                    SettingsView()
                case .profile(let userId):
                    ProfileView(userId: userId)
                }
            }
        }
    }

    // Programmatic navigation
    func navigateToSettings() {
        path.append(Route.settings)
    }

    func popToRoot() {
        path.removeLast(path.count)
    }
}

Usage

This skill activates automatically when working with Swift/SwiftUI files or when the user mentions iOS/macOS/SwiftUI development.

Explicit invocation:

/swift-swiftui help me refactor this view to use @Observable
/swift-swiftui create a settings screen with navigation
/swift-swiftui fix state management in this component

Source

git clone https://github.com/ojowwalker77/Claude-Matrix/blob/main/skills/swift-swiftui/SKILL.mdView on GitHub

Overview

This skill provides expert-level guidance for Swift and SwiftUI development, with a focus on modern patterns and iOS 17+/macOS 14+ best practices. It covers state management using @Observable, architecture choices like MVVM and TCA, and production-ready code generation tailored to real-world projects.

How This Skill Works

When you ask for Swift/SwiftUI guidance, the skill applies the documented modern patterns (e.g., @Observable, @Bindable, MVVM vs. TCA) to generate concrete code samples and actionable architecture recommendations. It selects the appropriate property wrappers and patterns based on the scenario and outputs production-ready snippets and best practices.

When to Use It

  • Writing SwiftUI code for a new iOS 17+/macOS 14+ app (UI, bindings, and state management).
  • Refactoring to modern state management using @Observable instead of ObservableObject.
  • Fixing a SwiftUI view or architecture with MVVM or TCA guidance.
  • Designing app architecture and data flow (MVVM with @Observable, or TCA) for scalable apps.
  • Optimizing for production-ready code with anti-pattern avoidance and performance tips.

Quick Start

  1. Step 1: Decide between MVVM with @Observable or a TCA approach based on app scale.
  2. Step 2: Define your model as an @Observable class and use @Bindable in child views that need binding.
  3. Step 3: Build a small feature end-to-end to validate the chosen pattern and iterate.

Best Practices

  • Prefer @Observable over ObservableObject for iOS 17+ apps to leverage modern reactivity.
  • Use the Property Wrapper Decision Tree to pick between @State, @Binding, @Observable, and other wrappers.
  • Adopt MVVM with @Observable for most apps; reserve TCA for large teams or complex apps.
  • Avoid anti-patterns like initializing @ObservedObject directly; use @StateObject or @State where appropriate.
  • Preserve data on errors (don’t clear UI data on failure; show errors while keeping existing state intact).

Example Use Cases

  • A login/profile screen using @Bindable to edit fields in a parent view model.
  • A parent view passes a read-only view model to a child view without extra wrappers.
  • An MVVM example where a SwiftUI view reads and updates an @Observable ViewModel.
  • A refactor from ObservableObject to @Observable in a simple feature module.
  • A minimal app using MVVM with AppStorage/Environment for global state management.

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers