Swift language fundamentals (5.10+ / 6.x). Covers optionals, value vs reference semantics, protocols & generics, Swift Concurrency (async/await, actors, Sendable, structured tasks), Result Builders, and Apple platform interop. USE WHEN: user mentions "Swift", "SwiftUI", "async/await Swift", "actor", "Sendable", "Codable", "Combine", "Result Builder", "Apple Keychain", "Secure Enclave", "iOS native" DO NOT USE FOR: reviewing existing Swift code - use `review/swift`, which covers retain cycles and the concurrency checking that is a per-target setting DO NOT USE FOR: SwiftUI screen layouts in depth - use SwiftUI-specific skill if exists DO NOT USE FOR: Compose iOS via Skia - use `frontend-frameworks/compose-multiplatform` DO NOT USE FOR: Kotlin/Native ↔ Swift bridging - use `languages/uniffi`

GitHub
Install command
npx skhub add claude-dev-suite/swift
Markdown
SKILL.md

Swift Core Knowledge

References: concurrency.md for async/await, actors, Sendable, structured tasks. interop.md for ObjC, C, and Rust (cinterop) bridging, Keychain, Secure Enclave.

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: swift.

Optionals

var name: String = "Alice"           // Non-optional
var maybe: String? = nil             // Optional (sugar for Optional<String>)

// Force-unwrap (avoid)
let n = maybe!                       // Crash if nil

// Optional binding
if let n = maybe {
    print("got \(n)")
}

// Guard (early exit)
func greet(_ name: String?) {
    guard let name else { return }
    print("Hello, \(name)")
}

// Nil coalescing
let display = maybe ?? "Anonymous"

// Optional chaining
let len = maybe?.count               // Int?

Use guard let name else { ... } (Swift 5.7+) — implicit shadow shorter than guard let name = name else.

Value vs Reference Types

KindSemanticsAllocationUse for
structValue (copied on assign/pass)Stack (usually)Models, lightweight data, thread-safe by default
enumValueStackDiscriminated unions, sealed states
classReference (shared identity)HeapIdentity, inheritance, ObjC interop
actorReference + isolatedHeapMutable state across concurrency
struct Point { var x: Double; var y: Double }
var a = Point(x: 1, y: 2)
var b = a            // copy
b.x = 10
// a.x still 1, b.x is 10

class Node { var value: Int = 0 }
let n1 = Node()
let n2 = n1          // same instance
n2.value = 42        // n1.value also 42

Default to struct. Use class only for identity, mutable shared state, or ObjC inheritance.

Enums with Associated Values

enum NetworkResult<Success> {
    case success(Success)
    case failure(NetworkError)
    case loading
}

enum NetworkError: Error {
    case unauthorized
    case server(code: Int, body: String)
    case timeout(after: TimeInterval)
}

func handle<T>(_ result: NetworkResult<T>) -> String {
    switch result {
    case .success(let value):
        return "ok: \(value)"
    case .failure(.unauthorized):
        return "login"
    case .failure(.server(let code, _)):
        return "server \(code)"
    case .failure(.timeout(let t)):
        return "timeout \(t)"
    case .loading:
        return "loading"
    }
}

switch is exhaustive — no default needed when all cases covered. Compiler enforces.

Protocols & Generics

protocol Identifiable {
    associatedtype ID: Hashable
    var id: ID { get }
}

struct User: Identifiable {
    let id: Int
    let name: String
}

// Protocol-oriented design
protocol Drawable { func draw() }

extension Drawable where Self: Identifiable, Self.ID == Int {
    func describe() -> String { "drawable id=\(id)" }
}

// Generic constraints
func first<C: Collection>(_ c: C) -> C.Element? where C.Element: Equatable {
    c.first
}

// Existential ('any') vs opaque ('some')
func makeShape() -> some Drawable { Circle() }     // concrete type, hidden
func loadShapes() -> [any Drawable] { [Circle(), Square()] }  // heterogeneous

Prefer some over any — opaque types preserve type identity for the compiler (no boxing). Use any only when truly heterogeneous.

Codable

struct User: Codable {
    let id: Int
    let name: String
    let email: String?
    let createdAt: Date

    enum CodingKeys: String, CodingKey {
        case id, name, email
        case createdAt = "created_at"
    }
}

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
decoder.keyDecodingStrategy = .convertFromSnakeCase  // alternative to CodingKeys

let user = try decoder.decode(User.self, from: jsonData)

let encoder = JSONEncoder()
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
let data = try encoder.encode(user)

For BHODL-style FFI, prefer Codable for IPC payloads and JSONEncoder/Decoder over manual parsing.

Error Handling

enum WalletError: Error {
    case insufficientFunds(Amount)
    case invalidAddress(String)
}

func send(amount: Amount, to address: String) throws -> Transaction {
    guard isValid(address) else { throw WalletError.invalidAddress(address) }
    guard hasFunds(amount) else { throw WalletError.insufficientFunds(amount) }
    return buildTx(amount, address)
}

// Call site
do {
    let tx = try send(amount: 1000, to: "bc1q...")
    print(tx)
} catch WalletError.insufficientFunds(let need) {
    print("need \(need)")
} catch {
    print("other error: \(error)")
}

// try? returns optional, try! force-unwraps (avoid)
let tx = try? send(amount: 1000, to: address)

Result Builders (DSLs)

Power SwiftUI's body and many Apple DSLs.

@resultBuilder
struct StringBuilder {
    static func buildBlock(_ components: String...) -> String {
        components.joined(separator: "\n")
    }
    static func buildEither(first: String) -> String { first }
    static func buildEither(second: String) -> String { second }
}

@StringBuilder
func greeting(name: String, formal: Bool) -> String {
    "Hello"
    if formal { "Mr/Ms \(name)" } else { name }
    "Welcome"
}

Property Wrappers

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

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

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

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

Common in SwiftUI (@State, @Binding, @StateObject, @Environment, @AppStorage).

Memory Management

ARC (Automatic Reference Counting). Watch for retain cycles.

class Node {
    var children: [Node] = []
    weak var parent: Node?           // weak breaks cycle
}

class ViewModel {
    private var task: Task<Void, Never>?

    func start() {
        task = Task { [weak self] in
            guard let self else { return }
            await self.load()
        }
    }
}

weak → optional, becomes nil when target deallocs. unowned → non-optional, crash on access if dealloc'd. Prefer weak unless lifetime guaranteed.

Concurrency — Essentials

func fetchUser(id: Int) async throws -> User {
    let (data, _) = try await URLSession.shared.data(from: url(id))
    return try JSONDecoder().decode(User.self, from: data)
}

// Parallel
async let user = fetchUser(id: 1)
async let posts = fetchPosts(userId: 1)
let result = try await (user, posts)

// Sequential
let user = try await fetchUser(id: 1)
let posts = try await fetchPosts(userId: user.id)

See concurrency.md for actors, Sendable, TaskGroup, AsyncStream, MainActor.

Anti-Patterns

Anti-patternWhy it's badCorrect approach
Force-unwrap ! everywhereCrash on nilguard let, if let, ??
class for value-like typesSurprising aliasingUse struct
Combine for new code (post-Swift Concurrency)Apple steering toward async/awaitPrefer AsyncSequence/AsyncStream
DispatchQueue.main.async from async codeUse @MainActorMainActor.run { ... } or annotate function
weak var everywhereHides ownership intentOnly break actual cycles
try! outside testsCrash on errortry? or proper do/catch
String-based KVO/selectorsNo type safetyUse KeyPath, Combine, async sequences
print for production loggingNo filter, no privacyUse os.Logger (import os)

Build & Tooling

// Package.swift (Swift Package Manager)
// swift-tools-version:6.0
import PackageDescription

let package = Package(
    name: "MyLib",
    platforms: [.iOS(.v17), .macOS(.v14)],
    products: [
        .library(name: "MyLib", targets: ["MyLib"]),
    ],
    dependencies: [
        .package(url: "https://github.com/apple/swift-algorithms.git", from: "1.2.0"),
    ],
    targets: [
        .target(name: "MyLib", dependencies: [
            .product(name: "Algorithms", package: "swift-algorithms"),
        ]),
        .testTarget(name: "MyLibTests", dependencies: ["MyLib"]),
    ]
)
swift build                        # Build
swift test                         # Run XCTest
swift run                          # Run executable target
swift package update               # Update deps
xcodebuild -scheme MyApp test      # Xcode CI build

Testing

// XCTest (legacy but widely used)
import XCTest
@testable import MyLib

final class UserTests: XCTestCase {
    func testValidEmail() {
        let u = User(id: 1, name: "x", email: "x@y.z")
        XCTAssertTrue(u.email.contains("@"))
    }

    func testAsync() async throws {
        let user = try await fetchUser(id: 1)
        XCTAssertEqual(user.id, 1)
    }
}

// Swift Testing (Swift 6+ — recommended for new code)
import Testing

@Suite struct UserTests {
    @Test func validEmail() {
        let u = User(id: 1, name: "x", email: "x@y.z")
        #expect(u.email.contains("@"))
    }

    @Test(arguments: [1, 2, 3])
    func userExists(id: Int) async throws {
        let user = try await fetchUser(id: id)
        #expect(user.id == id)
    }
}

When NOT to Use This Skill

ScenarioUse Instead
KMP from Rust → Swift bindingslanguages/uniffi
Compose Multiplatform iOS UIfrontend-frameworks/compose-multiplatform
iOS Keychain/Secure Enclave deep diveinterop.md
SwiftUI screen-by-screen architectureSwiftUI-specific skill (TBD)
ObjC migrationinterop.md
Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

MIT

Source path

skills/languages/swift

Default branch

main

Latest commit

9496306

Tree SHA

fe4e2f1