Swift essentials
The Swift concepts that trip people up first, and the idioms that fix them.
24 cardsBeginnerCode
Download the deck Get StackCards
Open the downloaded file on your iPhone or iPad and choose StackCards. It is also in the app: Library tab, then Add to my library.
What is inside
let vs varlet is a constant that can't be reassigned. var can change.
let name = "Ana" var score = 0
Declare an optionalA type that holds a value or nothing (nil).
var nickname: String? = nil
Unwrap with if letRuns the block only when there is a value.
if let nickname {
print(nickname)
}Unwrap with guard letExits early and keeps the value for the rest of the scope.
guard let user else { return }Default for nilThe nil-coalescing operator.
let name = nickname ?? "Guest"
Optional chainingStops and returns nil if anything is nil.
let count = user?.address?.street.count
Force unwrapCrashes if the value is nil. Use only when nil is truly impossible.
let value = text!
Define a structA value type: copied when assigned or passed.
struct Point {
var x: Double
var y: Double
}Define a classA reference type: shared when assigned or passed.
final class Counter {
var value = 0
}struct vs classStructs copy, classes share. Prefer structs unless you need identity or inheritance.
Define an enum with dataEach case can carry its own values.
enum Result {
case success(String)
case failure(Error)
}Switch over an enumThe switch must cover every case.
switch result {
case .success(let text): print(text)
case .failure(let error): print(error)
}Define a protocolA contract a type can promise to follow.
protocol Greeter {
func greet() -> String
}Extend an existing typeAdds methods without touching the original.
extension String {
var shout: String { uppercased() + "!" }
}Map, filter, reduceTransform, keep, and combine collections.
let sum = nums.filter { $0 > 0 }.map { $0 * 2 }.reduce(0, +)Closure syntaxAn unnamed function you can pass around.
let add = { (a: Int, b: Int) in a + b }Throw and catchFunctions that can fail are marked throws and called with try.
do {
try save()
} catch {
print(error)
}Async and awaitCall asynchronous code without callbacks.
let data = try await load()
What does @State do?Gives a SwiftUI view its own source of truth. When it changes, the view redraws.
@State private var count = 0
What does @Binding do?A two-way connection to a value owned by another view.
@Binding var isOn: Bool
What does @Observable do?Makes a class publish changes so any view that reads it updates automatically.
@Observable final class Model { var count = 0 }Why mark a class final?It can't be subclassed, which is clearer and lets the compiler optimize.
Weak referenceDoesn't keep an object alive. It becomes nil when the object goes away. Used to break retain cycles.
weak var delegate: Delegate?
What is a retain cycle?Two objects holding strong references to each other so neither is ever freed.