home / skills / willsigmon / sigstack / swift-expert

This skill provides Swift and SwiftUI expert guidance for fixing bindings, actor isolation, @Observable migrations, and common compiler errors to improve apps.

npx playbooks add skill willsigmon/sigstack --skill swift-expert

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
1.3 KB
---
name: Swift Expert
description: Swift/SwiftUI issues - compiler errors, bindings, @Observable, actor isolation, best practices
allowed-tools: Read, Edit, Grep
model: sonnet
---

# Swift Expert

Swift and SwiftUI expertise for Leavn app.

## Binding Fixes
Problem: `$viewModel.property` errors
Fix: Add `@Bindable` wrapper in View:
```swift
@Bindable var viewModel: MyViewModel
```

## Actor Isolation (Swift 6)
- `@MainActor` for UI-touching code
- `nonisolated` for pure functions
- `Task { @MainActor in }` for async UI updates
- Never access @MainActor properties in deinit

## @Observable Migration
Old: `@Published var x` + `ObservableObject`
New: `@Observable class` + plain `var x`
View: `@State var vm = ViewModel()` (not @StateObject)

## SwiftUI Anti-Patterns
- Heavy computation in View body → Extract to ViewModel
- @State for reference types → Use @StateObject/@State with @Observable
- Missing @MainActor on ViewModels → Add it
- Force unwrapping in Views → Use nil coalescing

## Common Compiler Errors
- "Cannot convert" → Check Optional unwrapping
- "Actor-isolated" → Add @MainActor or nonisolated
- "Missing conformance" → Add protocol or use type erasure
- "Ambiguous" → Add explicit type annotation

Use when: Swift errors, SwiftUI bugs, migration issues, best practices

Overview

This skill provides practical Swift and SwiftUI guidance for fixing compiler errors, migration to the new observation model, actor-isolation issues, and UI binding problems. It focuses on concrete fixes developers can apply quickly in app views and view models. The goal is to reduce time spent debugging SwiftUI quirks and modernize code to Swift 5/6 patterns.

How this skill works

I inspect common compiler messages, SwiftUI binding failures, and actor-isolation diagnostics and map them to minimal, safe code changes. I recommend specific attribute usage (@Observable, @Bindable, @MainActor, nonisolated) and state/property wrappers for views and view models. I also point out anti-patterns to extract work into view models and give targeted fixes for migration issues.

When to use it

  • You get `$viewModel.property` or binding conversion errors in a SwiftUI View.
  • Compiler reports actor-isolated access or actor-related concurrency errors.
  • Migrating from ObservableObject/@Published to the new @Observable model.
  • SwiftUI view body becomes slow or contains heavy computation.
  • You see ambiguous type, missing conformance, or optional conversion compiler errors.

Best practices

  • Use @Observable on view models and plain vars instead of ObservableObject+@Published when migrating.
  • Declare view model properties in views with @Bindable or @State/@StateObject depending on ownership.
  • Mark UI-touching view models with @MainActor; mark pure helpers nonisolated.
  • Avoid heavy computation inside View.body—move logic to view models or computed properties on models.
  • Prefer nil-coalescing or conditional rendering over force-unwrapping in views.
  • Add explicit type annotations when the compiler reports ambiguous types.

Example use cases

  • Fixing a binding error by changing a view property to @Bindable var viewModel: MyViewModel.
  • Resolving actor isolation by annotating a view model with @MainActor or wrapping UI updates in Task { @MainActor in ... }.
  • Migrating a class from ObservableObject/@Published to @Observable and updating view storage to @State var vm = ViewModel().
  • Eliminating a slow view by moving heavy calculations into a background task or view model.
  • Addressing a ‘missing conformance’ error by adding the protocol or applying type erasure to the offending type.

FAQ

When should I use @Bindable vs @StateObject?

@Bindable is for binding into an @Observable value exposed by the view. Use @StateObject when you own a reference-type view model that conforms to older ObservableObject semantics; prefer @State with @Observable view models after migration.

How do I stop actor-isolated errors touching UI state?

Mark the view model or UI-touching methods with @MainActor, or make helper methods nonisolated if they are pure. For async updates, use Task { @MainActor in ... } to hop to the main actor.