Swift cheat sheet

A scannable Swift reference: 28 short snippets across 13 topics, each linking back to the lesson it came from.

At a glance

TopicWhat it covers
Syntax and optionalsAn optional is a value that may be absent, written with a trailing ?. Swift will not let you use it until you havelesson
Structs, classes and protocolsThe compiler inserts strong references by default. A closure stored on an object that captures that object creates alesson
Closures and error handlingA closure is a function you can pass around. Swift gives it compact syntax — trailing closures, shorthand argumentlesson
Setting up Swift: Xcode, Swift Package Manager and Swift 6A common and healthy layout is a thin app target that imports one or more local packages. The logic becomes testablelesson
Generics, opaque types and protocol designFavour protocol composition (Codable & Sendable) over deep inheritance, and inject dependencies as protocollesson
Collections, strings and the standard libraryArrays, dictionaries and sets, map and filter and reduce, String versus Substring, Unicode and grapheme clusters, Datelesson
Swift 6 concurrency: tasks, actors and SendableTask and TaskGroup, async let, actor isolation, MainActor, Sendable checking, structured cancellation and the data-racelesson
SwiftUI: views, state and navigationA typed path array is the whole navigation state. Because it is a value, you can save it, restore it, or test a deeplesson
Networking, persistence and CodableURLSession with async and await, JSONDecoder and CodingKeys, mapping errors, caching, UserDefaults, file storage andlesson
Testing with XCTest and Swift TestingA protocol and a stub is usually enough. Reach for a generated mock only when you need to verify call order or argumentlesson
Memory management, ARC and performanceStrong, weak and unowned references, capture semantics, value-type copying, autorelease, and using Instruments to findlesson
Macros, property wrappers and result buildersWrite a property wrapper, build a result builder, understand the macro system and its limits, and know how to readlesson
Packaging, build configuration and distributionAn unshared scheme lives only on the machine that created it. Commit the scheme, or CI will fail with a message about alesson

Quick snippets

Syntax and optionals

Values, functions, control flow

let name = "Ada"            // constant, type inferred as String
var score = 0               // variable
let ratio: Double = 0.75    // explicit type when it is not obvious

func greet(_ who: String, greeting: String = "Hello") -> String {
    return greeting + ", " + who
}

greet("Ada")                            // "Hello, Ada"
greet("Ada", greeting: "Welcome")       // argument labels are part of the API

let label = score == 0 ? "empty" : "scored"

… 11 more lines in the full lesson.

Optionals

struct User {
    let email: String
    let phone: String?
}

func contact(_ user: User?) -> String {
    guard let email = user?.email, !email.isEmpty else { return "unknown" }
    let phone = user?.phone ?? "no phone"
    return email + " / " + phone
}

let maybe: Int? = Int("42")        // Int("abc") would be nil, not a crash

… 6 more lines in the full lesson.

Full lesson: Syntax and optionals →

Structs, classes and protocols

Structs: value semantics

struct Point: Equatable {
    var x: Double
    var y: Double

    // memberwise init is generated, so Point(x: 1, y: 2) already works
}

struct Counter {
    private(set) var value = 0

    mutating func increment() { value += 1 }   // mutating: changes a value type
}

… 8 more lines in the full lesson.

Classes and inheritance

class Account {
    let owner: String
    private(set) var balance: Int

    init(owner: String, opening: Int = 0) {
        self.owner = owner
        self.balance = opening
    }

    func deposit(_ amount: Int) {
        precondition(amount > 0, "amount must be positive")
        balance += amount

… 13 more lines in the full lesson.

Protocols and default implementations

protocol Identifiable {
    var id: String { get }
}

protocol Persistable {
    func save() throws
    func describe() -> String
}

extension Persistable {
    func describe() -> String { return "record " + id }   // reusable default
}

… 16 more lines in the full lesson.

Full lesson: Structs, classes and protocols →

Closures and error handling

Closures

let numbers = [3, 1, 2]

// full form
let sorted1 = numbers.sorted(by: { (a: Int, b: Int) -> Bool in a < b })
// shorthand argument names, implicit return
let sorted2 = numbers.sorted { $0 < $1 }

var completions: [() -> Void] = []

func loadRemote(with completion: @escaping (Result<String, Error>) -> Void) {
    completions.append(completion)          // escaping: outlives the call
}

… 11 more lines in the full lesson.

Throwing and catching

enum ParseError: Error, Equatable {
    case empty
    case notANumber(String)
}

func parse(_ text: String) throws -> Int {
    let trimmed = text.trimmingCharacters(in: .whitespaces)
    guard !trimmed.isEmpty else { throw ParseError.empty }
    guard let value = Int(trimmed) else { throw ParseError.notANumber(trimmed) }
    return value
}

… 13 more lines in the full lesson.

Errors with async and await

func fetchUser(id: String) async throws -> User {
    let (data, response) = try await URLSession.shared.data(from: url)
    guard let http = response as? HTTPURLResponse, http.statusCode == 200 else {
        throw ParseError.empty
    }
    return try JSONDecoder().decode(User.self, from: data)
}

func load() async {
    do {
        let user = try await fetchUser(id: "42")
        print(user.email)

… 6 more lines in the full lesson.

Full lesson: Closures and error handling →

Setting up Swift: Xcode, Swift Package Manager and Swift 6

Toolchain and project choices

# install a toolchain from swift.org, or use the one inside Xcode
swift --version
swiftly install latest        # a version manager, keeps several toolchains side by side
swiftly use 6.0.3

xcrun --sdk macosx --show-sdk-version

Building without Xcode

swift package init --type library
swift build                      # debug
swift build -c release
swift test --parallel
swift run reports-cli --help
swift package show-dependencies --format json
swift package resolve            # after editing Package.swift
swift package diagnose-api-breaking-changes 1.2.0

Reading a Package.swift

// swift-tools-version: 6.0
import PackageDescription

let package = Package(
    name: "Reports",
    platforms: [.macOS(.v14), .iOS(.v17)],
    products: [
        .library(name: "ReportsCore", targets: ["ReportsCore"]),
        .executable(name: "reports-cli", targets: ["ReportsCLI"]),
    ],
    dependencies: [
        .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.5.0"),

… 16 more lines in the full lesson.

Full lesson: Setting up Swift: Xcode, Swift Package Manager and Swift 6 →

Generics, opaque types and protocol design

Generic functions and constraints

func firstIndex<T: Collection>(of value: T.Element, in collection: T) -> T.Index?
where T.Element: Equatable {
    collection.firstIndex(of: value)
}

// a where clause on the extension, not on every method
extension Sequence where Element: Numeric {
    func total() -> Element { reduce(.zero, +) }
}

[1, 2, 3].total()             // 6
[1.5, 2.5].total()            // 4.0

… 12 more lines in the full lesson.

some versus any

protocol Shape {
    func area() -> Double
}

struct Circle: Shape {
    let radius: Double
    func area() -> Double { .pi * radius * radius }
}

// opaque: the caller knows it is a Shape, the concrete type stays private
func makeDefaultShape() -> some Shape { Circle(radius: 1) }

… 10 more lines in the full lesson.

Full lesson: Generics, opaque types and protocol design →

Collections, strings and the standard library

Choosing the right container

var scores: [String: Int] = ["ada": 91, "grace": 87]
let visited: Set<String> = ["home", "search", "home"]     // two elements

scores["linus"] = 78
scores["ada", default: 0] += 5        // avoids a force unwrap
let grouped = Dictionary(grouping: scores.keys, by: { $0.first! })

let sorted = scores.sorted { $0.value > $1.value }
let top = scores.max { $0.value < $1.value }              // ("ada", 96)

// transform in one pass instead of building intermediate arrays
let summary = scores

… 7 more lines in the full lesson.

Strings, Substring and Unicode

let text = "Café naïve"       // combining marks

text.count                      // 11 grapheme clusters, not 13 scalars
text.utf8.count                 // bytes on the wire
text.unicodeScalars.count       // scalars

let index = text.index(text.startIndex, offsetBy: 4)
let prefix = text[..<index]     // Substring, shares storage with text

// a Substring keeps the whole original string alive; convert when it escapes
let piece: String = String(prefix)

… 7 more lines in the full lesson.

Dates, calendars and Codable

let now = Date.now
let calendar = Calendar(identifier: .gregorian)
let startOfDay = calendar.startOfDay(for: now)
let days = calendar.dateComponents([.day, .month, .year], from: now)

let formatter = Date.FormatStyle(date: .abbreviated, time: .shortened)
    .locale(Locale(identifier: "en_GB"))
let label = now.formatted(formatter)

// time zones change; a Date is an instant, not a wall-clock time
let deadline = calendar.date(byAdding: .day, value: 30, to: now)!
let daysLeft = calendar.dateComponents([.day], from: now, to: deadline).day ?? 0

… 15 more lines in the full lesson.

Full lesson: Collections, strings and the standard library →

Swift 6 concurrency: tasks, actors and Sendable

Data-race safety in practice

// WRONG in Swift 6: the closure runs off the main actor
// and touches main-actor state without isolation
@MainActor
final class Feed {
    var items: [String] = []

    func load() async {
        let fetched = await fetchItems()
        items = fetched              // ok: still on the main actor
    }
}

… 12 more lines in the full lesson.

Full lesson: Swift 6 concurrency: tasks, actors and Sendable →

SwiftUI: views, state and navigation

Connecting a view to async data

struct ArticleDetail: View {
    let id: Int
    @State private var article: Article?
    @State private var error: String?

    var body: some View {
        Group {
            if let article {
                ScrollView {
                    Text(article.title).font(.title)
                    Text(article.body)
                }

… 16 more lines in the full lesson.

Full lesson: SwiftUI: views, state and navigation →

Networking, persistence and Codable

Caching and background refresh

actor ArticleCache {
    private var entries: [Int: (article: Article, savedAt: Date)] = [:]

    func article(_ id: Int, maxAge: TimeInterval = 300) -> Article? {
        guard let entry = entries[id],
              Date.now.timeIntervalSince(entry.savedAt) < maxAge else { return nil }
        return entry.article
    }

    func store(_ article: Article) {
        entries[article.id] = (article, .now)
    }

… 8 more lines in the full lesson.

Full lesson: Networking, persistence and Codable →

Testing with XCTest and Swift Testing

Running tests in CI

# packages: fast, no simulator needed
swift test --parallel --enable-code-coverage

# Apple apps: a specific simulator, result bundle for the report
xcodebuild test \
  -scheme App -destination 'platform=iOS Simulator,name=iPhone 16' \
  -enableCodeCoverage YES -resultBundlePath build/TestResults.xcresult

xcrun xccov view --report --json build/TestResults.xcresult > coverage.json

Full lesson: Testing with XCTest and Swift Testing →

Memory management, ARC and performance

Profiling with Instruments

# leaks and allocations while exercising the app
xcrun xctrace record --template "Leaks" \
  --launch com.example.app --output leaks.trace --time-limit 90s

# what is burning CPU during a specific interaction
xcrun xctrace record --template "Time Profiler" \
  --launch com.example.app --output cpu.trace --time-limit 60s

# memory graph in Xcode: Debug > Memory Graph while the suspicious screen is open

ARC and reference cycles

final class Node {
    let name: String
    var parent: Node?              // strong by default: a cycle with children
    weak var delegate: NodeDelegate?

    init(name: String) { self.name = name }
}

// the classic cycle: a closure stored on the object captures self
final class Loader {
    var onFinish: (() -> Void)?

… 15 more lines in the full lesson.

Value types and copying

// copy-on-write: assignment is cheap until a mutation happens
var first = Array(repeating: 0, count: 1_000_000)
var second = first              // no copy yet, both share the buffer
second[0] = 1                   // now the buffer is copied exactly once
print(first[0], second[0])      // 0 1

// a large struct passed around is copied unless the compiler proves otherwise,
// so build it once and return it rather than through several transformation steps
struct Report { let rows: [Row]; let totals: [String: Decimal] }

func makeReport(_ rows: [Row]) -> Report {
    Report(rows: rows, totals: rows.reduce(into: [:]) { totals, row in

… 3 more lines in the full lesson.

Full lesson: Memory management, ARC and performance →

Macros, property wrappers and result builders

Property wrappers

@propertyWrapper
struct Clamped<Value: Comparable> {
    private var value: Value
    private 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 }

… 14 more lines in the full lesson.

Macros and generated code

// A freestanding macro expands at the call site
let name = #function
let file = #filePath
let warning = #warning("remove before release")

// An attached macro augments a declaration: the compiler requires
// a peer declaration generated by a compiler plugin.
@freestanding(expression)
macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "MacrosImpl", type: "StringifyMacro")

@attached(member, names: named(init(from:)))
public macro Codable() = #externalMacro(module: "MacrosImpl", type: "CodableMacro")

… 8 more lines in the full lesson.

Full lesson: Macros, property wrappers and result builders →

Packaging, build configuration and distribution

Distribution

# archive and export for the App Store
xcodebuild archive -project App.xcodeproj -scheme App \
  -destination "generic/platform=iOS" -archivePath build/App.xcarchive

xcodebuild -exportArchive -archivePath build/App.xcarchive \
  -exportOptionsPlist Config/ExportOptions.plist -exportPath build/ipa

# server-side Swift on Linux
swift build -c release --static-swift-stdlib
docker build -t registry.example.com/reports:1.4.0 .
docker push registry.example.com/reports:1.4.0

Build settings and xcconfig

// Config/Shared.xcconfig
PRODUCT_BUNDLE_IDENTIFIER = com.example.app
MARKETING_VERSION = 2.4.0
CURRENT_PROJECT_VERSION = 1
SWIFT_VERSION = 6.0
SWIFT_STRICT_CONCURRENCY = complete
ENABLE_USER_SCRIPT_SANDBOXING = YES

// Config/Debug.xcconfig
#include "Shared.xcconfig"
BUNDLE_ID_SUFFIX = .debug
API_BASE_URL = https:/$()/staging.api.example.com

… 6 more lines in the full lesson.

Dependencies and schemes

// a shared scheme committed to the repository is what CI runs
// App.xcodeproj/xcshareddata/xcschemes/App.xcscheme
let scheme = """
<Scheme LastUpgradeVersion="1600" version="1.7">
  <TestAction buildConfiguration="Debug">
    <Testables>
      <TestableReference skipped="NO">
        <BuildableReference BuildableIdentifier="primary"
          BlueprintName="AppTests" BuildableName="AppTests.xctest"
          ReferencedContainer="container:App.xcodeproj"/>
      </TestableReference>
    </Testables>

… 3 more lines in the full lesson.

Full lesson: Packaging, build configuration and distribution →

FAQ

Is this Swift cheat sheet free to use?
Yes. No sign-up and no tracking: the page is static, every example is on the page itself, and you can print it or save it as a one-page reference.
Where do the examples come from?
Every snippet is taken from the 13 lessons of the Swift course on this site, and each section links back to the lesson it was pulled from.
How do I go deeper than a cheat sheet?
Open the full Swift course — it carries the worked explanations, the edge cases and the exercises behind every line here.

Android iOS Flutter React Native Kotlin

Last refreshed 2026-09-27.