Claude
Skills
Sign in
Back

swift-language

Included with Lifetime
$97 forever

Apply modern Swift language patterns and idioms for non-concurrency, non-SwiftUI code. Covers if/switch expressions (Swift 5.9+), typed throws (Swift 6+), result builders, property wrappers, opaque and existential types (some vs any), guard patterns, Never type, Regex builders (Swift 5.7+), basic Codable shaping (CodingKeys, custom decoding, nested containers), modern collection APIs (count(where:), contains(where:), replacing()), basic FormatStyle usage, and string interpolation patterns. Use when writing core Swift code involving generics, protocols, enums, closures, or modern language features; route deep Codable to swift-codable, detailed formatting/localization to swift-formatstyle, and API naming to swift-api-design-guidelines.

Design

What this skill does


# Swift Language Patterns

Core Swift language features and modern syntax patterns targeting Swift 6.3. Covers language constructs, type system features, basic Codable,
string and collection APIs, basic formatting, C interop (`@c`), module disambiguation (`ModuleName::symbol`), and performance attributes (`@specialized`, `@inline(always)`). For `@c` corrections, enumerate invalid Swift-only signature types: `String`, `Array`, `UnsafeBufferPointer`, closures, and generic placeholders. Route deeper Codable/API decoding to `swift-codable`, detailed formatting/localization to `swift-formatstyle`, API naming to `swift-api-design-guidelines`, concurrency to `swift-concurrency`, and SwiftUI state/view work to `swiftui-patterns`.

## Contents

- [If/Switch Expressions](#ifswitch-expressions)
- [Typed Throws](#typed-throws)
- [Result Builders](#result-builders)
- [Property Wrappers](#property-wrappers)
- [Opaque and Existential Types](#opaque-and-existential-types)
- [Guard Patterns](#guard-patterns)
- [Never Type](#never-type)
- [Regex Builders](#regex-builders)
- [Codable Best Practices](#codable-best-practices)
- [Modern Collection APIs](#modern-collection-apis)
- [FormatStyle](#formatstyle)
- [String Interpolation](#string-interpolation)
- [Common Mistakes](#common-mistakes)
- [Review Checklist](#review-checklist)
- [References](#references)

## If/Switch Expressions

Swift 5.9+ allows `if` and `switch` as expressions that return values. Use them
to assign, return, or initialize directly.

```swift
// Assign from if expression
let icon = if isComplete { "checkmark.circle.fill" } else { "circle" }

// Assign from switch expression
let label = switch status {
case .draft: "Draft"
case .published: "Published"
case .archived: "Archived"
}

// Works in return position
func color(for priority: Priority) -> Color {
    switch priority {
    case .high: .red
    case .medium: .orange
    case .low: .green
    }
}
```

**Rules:**
- Every branch must produce a value of the same type.
- Multi-statement branches are not allowed -- each branch is a single expression.
- Wrap in parentheses when used as a function argument to avoid ambiguity.

## Typed Throws

Swift 6+ allows specifying the error type a function throws.

```swift
enum ValidationError: Error {
    case tooShort, invalidCharacters, alreadyTaken
}

func validate(username: String) throws(ValidationError) -> String {
    guard username.count >= 3 else { throw .tooShort }
    guard username.allSatisfy(\.isLetterOrDigit) else { throw .invalidCharacters }
    return username.lowercased()
}

// Caller gets typed error -- no cast needed
do {
    let name = try validate(username: input)
} catch {
    // error is ValidationError, not any Error
    switch error {
    case .tooShort: print("Too short")
    case .invalidCharacters: print("Invalid characters")
    case .alreadyTaken: print("Taken")
    }
}
```

**Rules:**
- Use `throws(SomeError)` only when callers benefit from exhaustive error
  handling. For mixed error sources, use untyped `throws`.
- `throws(Never)` marks a function that syntactically throws but never actually
  does -- useful in generic contexts.
- Typed throws propagate: a function calling `throws(A)` and `throws(B)` must
  itself throw a type that covers both (or use untyped `throws`).

## Result Builders

`@resultBuilder` enables DSL-style syntax. SwiftUI's `@ViewBuilder` is the most
common example, but you can create custom builders for any domain.

```swift
@resultBuilder
struct ArrayBuilder<Element> {
    static func buildBlock(_ components: [Element]...) -> [Element] {
        components.flatMap { $0 }
    }
    static func buildExpression(_ expression: Element) -> [Element] { [expression] }
    static func buildOptional(_ component: [Element]?) -> [Element] { component ?? [] }
    static func buildEither(first component: [Element]) -> [Element] { component }
    static func buildEither(second component: [Element]) -> [Element] { component }
    static func buildArray(_ components: [[Element]]) -> [Element] { components.flatMap { $0 } }
}

func makeItems(@ArrayBuilder<String> content: () -> [String]) -> [String] { content() }

let items = makeItems {
    "Always included"
    if showExtra { "Conditional" }
    for name in names { name.uppercased() }
}
```

**Builder methods:** `buildBlock` (combine statements), `buildExpression` (single value), `buildOptional` (`if` without `else`), `buildEither` (`if/else`), `buildArray` (`for..in`), `buildFinalResult` (optional post-processing).

## Property Wrappers

Custom `@propertyWrapper` types encapsulate storage and access patterns.

```swift
@propertyWrapper
struct Clamped<Value: Comparable> {
    private var value: Value
    let range: ClosedRange<Value>

    var wrappedValue: Value {
        get { value }
        set { value = min(max(newValue, range.lowerBound), range.upperBound) }
    }

    var projectedValue: ClosedRange<Value> { range }

    init(wrappedValue: Value, _ range: ClosedRange<Value>) {
        self.range = range
        self.value = min(max(wrappedValue, range.lowerBound), range.upperBound)
    }
}

// Usage
struct Volume {
    @Clamped(0...100) var level: Int = 50
}

var v = Volume()
v.level = 150   // clamped to 100
print(v.$level) // projected value: 0...100
```

**Design rules:**
- `wrappedValue` is the primary getter/setter.
- `projectedValue` (accessed via `$property`) provides metadata or bindings.
- Property wrappers can be composed: `@A @B var x` applies outer wrapper first.
- Do not use property wrappers when a simple computed property suffices.

## Opaque and Existential Types

### `some Protocol` (Opaque Type)

The caller does not know the concrete type, but the compiler does. The
underlying type is fixed for a given scope.

```swift
func makeCollection() -> some Collection<Int> {
    [1, 2, 3]  // Always returns Array<Int> -- compiler knows the concrete type
}
```

Use `some` for:
- Return types when you want to hide implementation but preserve type identity.
- Parameter types (Swift 5.7+): `some P` is shorthand for an unnamed generic
  parameter such as `<T: P>`.

### `any Protocol` (Existential Type)

An existential box that can hold any conforming type at runtime. It uses dynamic
dispatch and may allocate when the value does not fit in the inline buffer.

```swift
func process(items: [any StringProtocol]) {
    for item in items {
        print(item.uppercased())
    }
}
```

### When to choose

| Use `some` | Use `any` |
|---|---|
| Return type hiding concrete type | Heterogeneous collections |
| Function parameters (replaces simple generics) | Dynamic type erasure needed |
| Better performance (static dispatch) | Protocol has `Self` or associated type requirements you need to erase |

**Rule of thumb:** Default to `some`. Use `any` only when you need a
heterogeneous collection or runtime type flexibility.

## Guard Patterns

`guard` enforces preconditions and enables early exit. It keeps the happy path
left-aligned and reduces nesting.

```swift
func processOrder(_ order: Order?) throws -> Receipt {
    // Unwrap optionals
    guard let order else { throw OrderError.missing }

    // Validate conditions
    guard order.items.isEmpty == false else { throw OrderError.empty }
    guard order.total > 0 else { throw OrderError.invalidTotal }

    // Boolean checks
    guard order.isPaid else { throw OrderError.unpaid }

    // Pattern matching
    guard case .confirmed(let date) = order.status else {
        throw OrderError.notConfirmed
    }

    return Receipt(order: order, confirmedAt: date)
}
```

**Best practices:**
- Use `guard` for preconditions, `if` for branching logic.
- Combine related guards: `guard let a, let b else { return }`.
- The `else` block must exit scope: `return`, `throw`, `continue`, `break`, or
  `fatalError()`.
- Use shorthand unwrap: `guard let value else { ... }` (Swift 5.7+).

## Never Type

`Never` is an uninhabited type for code paths that never produce a value. It
works as Swift's

Related in Design