$npx -y skills add johnrogers/claude-swift-engineering --skill swift-styleSwift code style conventions for clean, readable code. Use when writing Swift code to ensure consistent formatting, naming, organization, and idiomatic patterns.
| 1 | # Swift Style Guide |
| 2 | |
| 3 | Code style conventions for clean, readable Swift code. |
| 4 | |
| 5 | ## Core Principles |
| 6 | |
| 7 | **Clarity > Brevity > Consistency** |
| 8 | |
| 9 | Code should compile without warnings. |
| 10 | |
| 11 | ## Naming |
| 12 | |
| 13 | - `UpperCamelCase` — Types, protocols |
| 14 | - `lowerCamelCase` — Everything else |
| 15 | - Clarity at call site |
| 16 | - No abbreviations except universal (URL, ID) |
| 17 | |
| 18 | ```swift |
| 19 | // Preferred |
| 20 | let maximumWidgetCount = 100 |
| 21 | func fetchUser(byID id: String) -> User |
| 22 | ``` |
| 23 | |
| 24 | ## Golden Path |
| 25 | |
| 26 | Left-hand margin is the happy path. Don't nest `if` statements. |
| 27 | |
| 28 | ```swift |
| 29 | // Preferred |
| 30 | func process(value: Int?) throws -> Result { |
| 31 | guard let value = value else { |
| 32 | throw ProcessError.nilValue |
| 33 | } |
| 34 | guard value > 0 else { |
| 35 | throw ProcessError.invalidValue |
| 36 | } |
| 37 | return compute(value) |
| 38 | } |
| 39 | ``` |
| 40 | |
| 41 | ## Code Organization |
| 42 | |
| 43 | Use extensions and MARK comments: |
| 44 | |
| 45 | ```swift |
| 46 | class MyViewController: UIViewController { |
| 47 | // Core implementation |
| 48 | } |
| 49 | |
| 50 | // MARK: - UITableViewDataSource |
| 51 | extension MyViewController: UITableViewDataSource { } |
| 52 | ``` |
| 53 | |
| 54 | ## Spacing |
| 55 | |
| 56 | - Braces open on same line, close on new line |
| 57 | - One blank line between methods |
| 58 | - Colon: no space before, one space after |
| 59 | |
| 60 | ## Self |
| 61 | |
| 62 | Avoid `self` unless required by compiler. |
| 63 | |
| 64 | ```swift |
| 65 | // Preferred |
| 66 | func configure() { |
| 67 | backgroundColor = .systemBackground |
| 68 | } |
| 69 | ``` |
| 70 | |
| 71 | ## Computed Properties |
| 72 | |
| 73 | Omit `get` for read-only: |
| 74 | |
| 75 | ```swift |
| 76 | var diameter: Double { |
| 77 | radius * 2 |
| 78 | } |
| 79 | ``` |
| 80 | |
| 81 | ## Closures |
| 82 | |
| 83 | Trailing closure only for single closure parameter. |
| 84 | |
| 85 | ## Type Inference |
| 86 | |
| 87 | Let compiler infer when clear. For empty collections, use type annotation: |
| 88 | |
| 89 | ```swift |
| 90 | var names: [String] = [] |
| 91 | ``` |
| 92 | |
| 93 | ## Syntactic Sugar |
| 94 | |
| 95 | ```swift |
| 96 | // Preferred |
| 97 | var items: [String] |
| 98 | var cache: [String: Int] |
| 99 | var name: String? |
| 100 | ``` |
| 101 | |
| 102 | ## Access Control |
| 103 | |
| 104 | - `private` over `fileprivate` |
| 105 | - Don't add `internal` (it's the default) |
| 106 | - Access control as leading specifier |
| 107 | |
| 108 | ## Memory Management |
| 109 | |
| 110 | ```swift |
| 111 | resource.request().onComplete { [weak self] response in |
| 112 | guard let self else { return } |
| 113 | self.updateModel(response) |
| 114 | } |
| 115 | ``` |
| 116 | |
| 117 | ## Comments |
| 118 | |
| 119 | - Explain **why**, not what |
| 120 | - Use `//` or `///`, avoid `/* */` |
| 121 | - Keep up-to-date or delete |
| 122 | |
| 123 | ## Constants |
| 124 | |
| 125 | Use case-less enum for namespacing: |
| 126 | |
| 127 | ```swift |
| 128 | enum Math { |
| 129 | static let pi = 3.14159 |
| 130 | } |
| 131 | ``` |
| 132 | |
| 133 | ## Common Mistakes |
| 134 | |
| 135 | 1. **Abbreviations beyond URL, ID, UUID** — Abbreviations like `cfg`, `mgr`, `ctx`, `desc` hurt readability. Spell them out: `configuration`, `manager`, `context`, `description`. The three exceptions are URL, ID, UUID. |
| 136 | |
| 137 | 2. **Nested guard/if statements** — Deep nesting makes code hard to follow. Use early returns and guards to keep the happy path left-aligned. |
| 138 | |
| 139 | 3. **Inconsistent self usage** — Either always omit `self` (preferred) or always use it. Mixing makes code scanning harder and confuses capture semantics. |
| 140 | |
| 141 | 4. **Overly generic type names** — `Manager`, `Handler`, `Helper`, `Coordinator` are too vague. Names should explain responsibility: `PaymentProcessor`, `EventDispatcher`, `ImageCache`, `NavigationCoordinator`. |
| 142 | |
| 143 | 5. **Implied access control** — Don't skip access control. Explicit `private`, `public` helps future maintainers understand module boundaries. `internal` is default, so omit it. |