# Apple Swift

> Apple platform development with Swift, SwiftUI, async/await, and performance. Use when working with .swift files, Package.swift, Xcode projects, or building for iOS/macOS/watchOS/visionOS.

- Skill: `maroffo/apple-swift` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add maroffo/apple-swift`
- Raw SKILL.md: https://api.skillmd.com/api/skills/maroffo/apple-swift/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: maroffo (https://skillmd.com/u/maroffo)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/maroffo/apple-swift

---


# ABOUTME: Apple platform guide, Swift, SwiftUI, concurrency, testing, performance
# ABOUTME: Conventions, strict concurrency rules, MVVM + DI patterns, review checklists

# Apple Platform Development

## Quick Reference

```bash
# Build
xcodebuild -scheme MyApp -sdk iphoneos build
xcodebuild -scheme MyApp -sdk macosx build

# Tests (pick <booted device> from: xcrun simctl list devices | grep Booted)
xcodebuild test -scheme MyApp -destination 'platform=iOS Simulator,name=<booted device>'

# SwiftLint / SPM
swiftlint lint [--fix]
swift build && swift test && swift package resolve

# ast-grep
sg --pattern '@Observable final class $NAME { $$$ }' --lang swift
sg --pattern '@MainActor' --lang swift
```

**See also:** `_AST_GREP.md`, `_PATTERNS.md`, `source-control`, `references/`

---

## Version (determine, don't assume)

See `../_LANG_COMMON.md`. Fetch the truth:

```bash
swift --version                                 # local toolchain
xcodebuild -version                             # Xcode version
cat .swift-version 2>/dev/null                  # pinned toolchain (if present)
grep -E 'swift-tools-version' Package.swift     # SPM minimum
curl -s https://api.github.com/repos/swiftlang/swift/releases/latest | jq -r .tag_name  # latest upstream
```

---

## Pre-Commit Verification (MANDATORY)

`make check && make test-e2e` must pass (enforced by the `pre-commit-gate` hook; see `../_LANG_COMMON.md`). What `make check` expands to for an Apple project:

```bash
swift build                                     # compilation check
swift test                                      # unit tests
swiftlint lint --strict                         # lint (fail on warnings)
swift-format lint --recursive Sources Tests     # formatting check
xcodebuild -scheme MyApp test \
  -destination 'platform=iOS Simulator,name=<booted device>'   # platform tests
```

Pick `<booted device>` from `xcrun simctl list devices | grep Booted` (do not hardcode a simulator model).

---

## SwiftUI

### Property Wrappers

| Wrapper | Use |
|---------|-----|
| `@State` | View-owned values, @Observable |
| `@Binding` | Two-way to parent |
| `@Bindable` | Two-way to @Observable props |
| `@Environment` | System/app values |
| `@StateObject` | View-owned ObservableObject (legacy) |

**View property order:** @Environment, let, @State/@Binding, computed, init, body, private methods

**View sizing:** <100 lines = single view; 100-200 = extract subviews; >200 = multiple files; business logic = @Observable VM; network/DB = repository pattern

For NavigationStack, SwiftData, MVVM, and DI patterns, see `references/swiftui-patterns.md`.

---

## Concurrency

### Common Fixes

| Error | Fix |
|-------|-----|
| Main actor isolation | Add `@MainActor` to class/func |
| Non-isolated access | Mark `nonisolated` |
| Sendable violation | Add `@unchecked Sendable` or fix |
| Protocol async | Require `async` in protocol |
| Closure capture | Use `@Sendable` closure |

### When to use what

| Use Case | Choice |
|----------|--------|
| One-shot network | async/await |
| Parallel fetches | async let / TaskGroup |
| Real-time streams | Combine / AsyncStream |
| UI events, debounce | Combine |

**NON-NEGOTIABLE:** UI updates always on `@MainActor`. Cross-actor value types must be `Sendable`. Respect task cancellation: check `Task.isCancelled` in long-running work.

For MainActor, parallel execution, and actor patterns, see `references/concurrency-patterns.md`.

---

## Architecture

**MVVM with @Observable:** `@Observable @MainActor final class VM` with `private(set)` properties, injected service protocols, `async` load methods with `defer { isLoading = false }`.

**DI:** Protocol-based with `EnvironmentKey` for SwiftUI injection.

**Coordinator pattern:** For flow-heavy apps, lift navigation state out of views into a Coordinator type owning a `NavigationPath` (or route enum) and exposing intents.

**Testing (Swift Testing):** `@Suite`, `@Test`, `#expect`. Parameterized with `arguments:`. Mock via protocol injection. XCTest still valid where needed (UI tests, legacy targets).

For full code examples, see `references/swiftui-patterns.md` and `references/swift6-patterns.md`.

---

## Review Checklists

**Concurrency:** MainActor for UI, Sendable for cross-actor data, task cancellation handled, no data races

**SwiftUI:** @Observable over ObservableObject where available, NavigationStack over NavigationView, `.task` over `.onAppear + Task`, LazyVStack for long lists

**CRITICAL:** Force unwrap without safety, UI updates off MainActor, data races, retain cycles

**HIGH:** Legacy ObservableObject when @Observable fits, NavigationView in new code

---

## Detailed References

- `references/swift6-patterns.md` - Strict concurrency migration, Sendable, actors, macros
- `references/swiftui-patterns.md` - NavigationStack, SwiftData, MVVM, dependency injection
- `references/concurrency-patterns.md` - async/await, TaskGroup, MainActor, actors, AsyncStream
- `references/performance.md` - Optimization, Instruments profiling, memory management

**Official:** [Swift](https://developer.apple.com/swift/) | [SwiftUI](https://developer.apple.com/documentation/swiftui/) | [SwiftData](https://developer.apple.com/documentation/swiftdata/)

**Libraries:** [TCA](https://github.com/pointfreeco/swift-composable-architecture) | [Snapshot Testing](https://github.com/pointfreeco/swift-snapshot-testing) | [SwiftLint](https://github.com/realm/SwiftLint)

