| name | apple-swift |
| description | 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. |
| compatibility | Requires Xcode and platform SDKs. Optional: SwiftLint. |
| allowed-tools | ["mcp__acp__Read","mcp__acp__Edit","mcp__acp__Write","mcp__acp__Bash"] |
ABOUTME: Apple platform guide, Swift, SwiftUI, concurrency, testing, performance
ABOUTME: Conventions, strict concurrency rules, MVVM + DI patterns, review checklists
Apple Platform Development
Quick Reference
xcodebuild -scheme MyApp -sdk iphoneos build
xcodebuild -scheme MyApp -sdk macosx build
xcodebuild test -scheme MyApp -destination 'platform=iOS Simulator,name=<booted device>'
swiftlint lint [--fix]
swift build && swift test && swift package resolve
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:
swift --version
xcodebuild -version
cat .swift-version 2>/dev/null
grep -E 'swift-tools-version' Package.swift
curl -s https://api.github.com/repos/swiftlang/swift/releases/latest | jq -r .tag_name
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:
swift build
swift test
swiftlint lint --strict
swift-format lint --recursive Sources Tests
xcodebuild -scheme MyApp test \
-destination 'platform=iOS Simulator,name=<booted device>'
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 | SwiftUI | SwiftData
Libraries: TCA | Snapshot Testing | SwiftLint