Short answer: Create a command-line project with swift package init --type executable and run it with swift run. Use let for constants and var for variables, unwrap optionals with if let, guard let or ??, and prefer struct (value type) over class. Model states with enum and switch, mark failing functions throws and call them with try. Swift 6 checks data races at compile time; use async/await, Task and actor for concurrent code.
The examples in this Swift cheat sheet were run with Swift 6.4 (swift-6.4-RELEASE) on Ubuntu 24.04 on 9 October 2026, using Swift Package Manager and Foundation on Linux.
Table of Contents
Swift Package Manager and toolchain
| Command | What it does |
|---|---|
swift --version | Show the compiler version |
swift package init --type executable | New command-line package in the current directory |
swift package init --type library | New library package |
swift run / swift run Demo --flag | Build and run (with arguments) |
swift build -c release | Optimised binary in .build/release/ |
swift test | Run tests (new packages use the Swift Testing library, @Test and #expect) |
swift package update | Update dependencies within Package.swift rules |
swiftc main.swift -o app | Compile a single file without a package |
swiftly install latest | Install or switch toolchains with swiftly, the installer swift.org recommends on Linux |
On Linux, Swift ships with Foundation, so String(contentsOfFile:), JSONEncoder, ProcessInfo and Process work as they do on macOS. Apple frameworks such as UIKit and SwiftUI are not available there.
Variables, strings and control flow
| Syntax | What it does | Example |
|---|---|---|
let | Constant; prefer it by default | let name = "web01" |
var | Variable | var port = 443; port += 1 |
| Type annotation | Optional when the type can be inferred | let ratio: Double = 0.75 |
"\(expr)" | String interpolation | "\(name):\(port)" |
""" ... """ | Multi-line string; indentation of the closing quotes is removed | |
0..<3 / 1...3 | Half-open / closed range | for i in 0..<3 { } |
stride(from:to:by:) | Stepped loop | stride(from: 10, to: 0, by: -5) |
while / repeat { } while | Loops | |
switch with ranges and lists | Must be exhaustive; no implicit fall-through | case 400..<500: |
if / switch expressions | Produce a value directly | let kind = if port > 1024 { "high" } else { "low" } |
let code = 404
let msg = switch code {
case 200: "ok"
case 301, 302: "redirect"
case 400..<500: "client error"
default: "other"
}
print(msg) // client error
Optionals
| Syntax | What it does |
|---|---|
var nick: String? = nil | A value that may be absent |
if let nick { ... } | Unwrap into a constant with the same name |
guard let p = Int(raw) else { return nil } | Unwrap or leave early; p stays in scope afterwards |
nick ?? "none" | Default value |
user?.address?.city | Optional chaining; the result is optional |
nick! | Force unwrap; crashes on nil, so avoid it outside tests |
func check(_ raw: String) -> Int? {
guard let p = Int(raw), (1...65535).contains(p) else {
return nil
}
return p
}
check("8080") // Optional(8080)
check("x") // nil
Collections and closures
| Syntax | What it does |
|---|---|
var nums = [5, 3, 8] | Array; append, sort(), count, first, contains |
nums.map { $0 * $0 } | Transform each element ($0 is the first argument) |
nums.filter { $0.isMultiple(of: 2) } | Keep matching elements |
nums.reduce(0, +) | Combine into one value |
["1", "x"].compactMap { Int($0) } | Map and drop nil results |
nums.sorted { $0 > $1 } | New sorted array with a trailing closure |
var ports = ["ssh": 22] | Dictionary; lookups return an optional |
ports["https"] = nil | Remove a key |
counts[w, default: 0] += 1 | Count with a default value |
let s: Set = ["a", "b"] | Set of unique values |
func greet(_ person: String, from city: String = "Leeds") -> String {
"Hello \(person) from \(city)" // single expression: implicit return
}
greet("Ali") // argument label omitted with _
greet("Sam", from: "York")
func bump(_ x: inout Int) { x += 1 }
var c = 1
bump(&c) // c == 2
Structs, classes, enums and protocols
struct Server: Codable, Equatable {
var name: String
var port: Int = 22
var address: String { "\(name):\(port)" } // computed property
mutating func setPort(_ p: Int) { port = p }
}
enum Event {
case login(user: String, ok: Bool)
case restart(String)
case quit
}
switch event {
case .login(let user, false): print("failed login \(user)")
case .login(let user, _): print("login \(user)")
case .restart(let svc): print("restart \(svc)")
case .quit: print("quit")
}
protocol Check {
var name: String { get }
func healthy() -> Bool
}
extension Check {
func healthy() -> Bool { true } // default implementation
}
extension Server: Check {} // Server already has `name`
| Syntax | Meaning |
|---|---|
struct | Value type: copied on assignment |
final class | Reference type: assignments share one instance |
enum Level: Int, CaseIterable | Raw values and Level.allCases |
func report(_ c: some Check) | Opaque generic parameter (static dispatch) |
let checks: [any Check] | Existential: mixed types behind one protocol |
func largest<T: Comparable>(_ xs: [T]) -> T? | Generic function with a constraint |
try JSONEncoder().encode(server) | JSON from a Codable type |
Error handling
enum ConfigError: Error {
case missing(String)
case badPort(String)
}
func parsePort(_ s: String) throws(ConfigError) -> Int { // typed throws
guard !s.isEmpty else { throw .missing("port") }
guard let p = Int(s), (1...65535).contains(p) else { throw .badPort(s) }
return p
}
do {
let p = try parsePort("70000")
print(p)
} catch .badPort(let raw) {
print("bad port \(raw)") // bad port 70000
} catch {
print("other: \(error)")
}
| Syntax | What it does |
|---|---|
throws / throws(MyError) | Function can throw any error / one error type |
try f() | Call a throwing function inside do or another throwing function |
try? f() | Returns nil on error |
try! f() | Crashes on error |
Result { try f() } | Capture success or failure as a value |
defer { ... } | Run cleanup when the scope exits |
Concurrency: async, await, tasks and actors
func fetchStatus(_ host: String) async -> Int {
try? await Task.sleep(for: .milliseconds(10))
return host.count
}
actor HitCounter { // serialises access to its state
private var hits = 0
func add() { hits += 1 }
func value() -> Int { hits }
}
async let a = fetchStatus("web01") // runs concurrently
async let b = fetchStatus("web02")
let both = await [a, b]
let results = await withTaskGroup(of: Int.self) { group in
for h in ["a", "bb", "ccc"] {
group.addTask { await fetchStatus(h) }
}
var out: [Int] = []
for await v in group { out.append(v) }
return out
}
Packages with swift-tools-version: 6.0 or later use the Swift 6 language mode, which turns data-race warnings into errors. Values sent between tasks must be Sendable; structs and enums of Sendable members qualify automatically. The migration guide explains how to adopt this in older code.
Files, processes and a log example
For server admins: count requests per client IP in an access log with Foundation.
import Foundation
let path = CommandLine.arguments.dropFirst().first ?? "/var/log/nginx/access.log"
guard let text = try? String(contentsOfFile: path, encoding: .utf8) else {
FileHandle.standardError.write(Data("cannot read \(path)\n".utf8))
exit(1)
}
var hits: [Substring: Int] = [:]
for line in text.split(separator: "\n") {
if let ip = line.split(separator: " ").first {
hits[ip, default: 0] += 1
}
}
for (ip, n) in hits.sorted(by: { $0.value > $1.value }).prefix(10) {
print(String(format: "%7d", n), ip)
}
| Syntax | What it does |
|---|---|
try String(contentsOfFile: p, encoding: .utf8) | Read a whole text file |
try text.write(toFile: p, atomically: true, encoding: .utf8) | Write a file |
FileManager.default.fileExists(atPath: p) | Check a path |
ProcessInfo.processInfo.environment["HOME"] | Environment variable |
let p = Process(); p.executableURL = URL(fileURLWithPath: "/usr/bin/uptime"); try p.run() | Run a program; call p.waitUntilExit() to wait |
Official documentation (checked 9 October 2026): The Swift Programming Language · Swift Standard Library · Install Swift on Linux · Swift Package Manager · Swift 6 Migration Guide (data-race safety) · Swift 6.4 Released
Swift Cheat Sheet at a glance


Related guides: Kotlin Cheat Sheet: Syntax, Null Safety and Collections · Dart 3 Cheat Sheet: Null Safety, Records, Patterns and async · TypeScript Cheat Sheet: Types, Generics and tsconfig.
Reading a lot of our guides? Go ad-free with srvScripts Pro for $6 a month. It also pays for new guides. Cancel any time.