# Swift Development

> Swift/SwiftUI iOS and macOS development — structure, patterns, best practices Use when this capability is needed.

- Skill: `tomevault-io/swift-development` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/swift-development`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/swift-development/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/swift-development

---


# SKILL: Swift Development

## Purpose
Build production-quality Swift applications following Apple's modern patterns.

## SwiftUI Architecture (MVVM)
```swift
// View — only layout, no business logic
struct UserListView: View {
    @StateObject private var viewModel = UserListViewModel()
    
    var body: some View {
        List(viewModel.users) { user in
            UserRowView(user: user)
        }
        .task { await viewModel.loadUsers() }
    }
}

// ViewModel — business logic, state management
@MainActor
class UserListViewModel: ObservableObject {
    @Published var users: [User] = []
    @Published var isLoading = false
    @Published var error: Error?
    
    private let repository: UserRepository
    
    init(repository: UserRepository = UserRepositoryImpl()) {
        self.repository = repository
    }
    
    func loadUsers() async {
        isLoading = true
        defer { isLoading = false }
        do {
            users = try await repository.fetchUsers()
        } catch {
            self.error = error
        }
    }
}

// Model — plain data, Codable for API
struct User: Identifiable, Codable, Equatable {
    let id: UUID
    let name: String
    let email: String
}
```

## Networking Pattern
```swift
// Use URLSession with async/await
actor NetworkService {
    private let session: URLSession
    private let decoder = JSONDecoder()
    
    init(session: URLSession = .shared) {
        self.session = session
    }
    
    func fetch<T: Decodable>(_ type: T.Type, from url: URL) async throws -> T {
        let (data, response) = try await session.data(from: url)
        
        guard let httpResponse = response as? HTTPURLResponse,
              200...299 ~= httpResponse.statusCode else {
            throw NetworkError.invalidResponse
        }
        
        return try decoder.decode(T.self, from: data)
    }
}
```

## State Management Rules
```
@State — local UI state (transient, owned by view)
@StateObject — local ViewModel (owned by view, persists)
@ObservedObject — external ViewModel (passed in, not owned)
@EnvironmentObject — dependency injection (global objects)
@Binding — two-way binding (passed from parent)
```

## Error Handling Pattern
```swift
enum AppError: LocalizedError {
    case networkError(Error)
    case decodingError
    case notFound
    
    var errorDescription: String? {
        switch self {
        case .networkError(let error): return error.localizedDescription
        case .decodingError: return "Unable to process response"
        case .notFound: return "Content not found"
        }
    }
}
```

## Testing Pattern
```swift
@MainActor
final class UserListViewModelTests: XCTestCase {
    var sut: UserListViewModel!
    var mockRepository: MockUserRepository!
    
    override func setUp() {
        mockRepository = MockUserRepository()
        sut = UserListViewModel(repository: mockRepository)
    }
    
    func testLoadUsersSucceeds() async {
        mockRepository.users = [User.mock]
        await sut.loadUsers()
        XCTAssertEqual(sut.users.count, 1)
        XCTAssertFalse(sut.isLoading)
    }
}
```

## Quality checks
- [ ] Views contain only layout code
- [ ] ViewModels are @MainActor
- [ ] Network calls are async/await (no completion handlers)
- [ ] Errors surfaced to UI with user-friendly messages
- [ ] Unit tests for all ViewModel logic
- [ ] Accessibility identifiers set for UI testing

---
> Source: [karvifi/OS](https://github.com/karvifi/OS) — distributed by [TomeVault](https://tomevault.io).
<!-- tomevault:4.0:skill_md:2026-05-23 -->

