Irbisa · Cheatsheet
Swift Generics & Advanced
Generics, opaque types, property wrappers, result builders, key paths
What does
Codabledo, and how do you decode JSON whose keys do not match your property names?import Foundation struct Article: Codable { let id: Int let title: String let authorName: String…What are generics in Swift, and what can a
whereclause express that angle brackets cannot?// Generic function: one implementation for every Comparable typefunc clamp<T: Comparable>(_ value: T, to range: ClosedRange<T>) -> T { min(max(value, range.lowerBound), range.upperBound)}print(clamp(15, to: 0...10)) // 10 (T == Int)print(clamp(0.5, to: 0...1)) // 0.5 (T == Double)…What is an associated type, what limits does it put on a protocol, and what do primary associated types change?
protocol Store<Item> { // Item is the primary associated type associatedtype Item: Identifiable func load(id: Item.ID) async throws -> Item func save(_ item: Item) async throws}…Which line in this code does not compile, and what does conditional conformance have to do with it?
struct Box<Value> { let value: Value}extension Box: Equatable where Value: Equatable {} struct Token { let raw: String } print(Box(value: 1) == Box(value: 1))print([Box(value: "a")] == [Box(value: "a")])print(Box(value: Token(raw: "a")) == Box(value: Token(raw: "a")))What is the difference between
someandanyin Swift, and how do both relate to generics?protocol Shape { func area() -> Double }struct Circle: Shape { let r: Double; func area() -> Double { .pi * r * r } }struct Square: Shape { let side: Double; func area() -> Double { side * side } } // some in a return: one hidden concrete type, chosen by the functionfunc unitShape() -> some Shape { Circle(r: 1) }…This function does not compile. Why, and how would you fix it?
protocol Shape { func area() -> Double }struct Circle: Shape { let r: Double; func area() -> Double { .pi * r * r } }struct Square: Shape { let side: Double; func area() -> Double { side * side } } func makeShape(rounded: Bool) -> some Shape { if rounded { return Circle(r: 1) } return Square(side: 2)}What does
@escapingmean, and why are closure parameters non-escaping by default?import Foundation final class ImageLoader { private var handlers: [(Data) -> Void] = [] // Called before the function returns: non-escaping, no annotation needed…What are key paths in Swift, and where would you use them?
struct User { var name: String var age: Int} let users = [User(name: "Ada", age: 36), User(name: "Linus", age: 29)]…How does a property wrapper work, and how do you write a custom one?
@propertyWrapperstruct Clamped<Value: Comparable> { private var value: Value private let range: ClosedRange<Value> init(wrappedValue: Value, _ range: ClosedRange<Value>) {…Find the bug:
finishedends up lower than the number of completed downloads, although every access to it goes through a lock.@propertyWrapperfinal class Locked<Value>: @unchecked Sendable { private let lock = NSLock() private var value: Value init(wrappedValue: Value) { value = wrappedValue } var wrappedValue: Value { get { lock.withLock { value } } set { lock.withLock { value = newValue } } }} final class DownloadStats: @unchecked Sendable { @Locked var finished = 0 func markFinished() { finished += 1 } // called from many download tasks}What is a result builder, and why does an
ifor aforinside a custom builder sometimes fail to compile?struct Step { let title: String } @resultBuilderenum StepsBuilder { static func buildExpression(_ step: Step) -> [Step] { [step] } // each line static func buildBlock(_ parts: [Step]...) -> [Step] { parts.flatMap { $0 } }…What is the difference between
SequenceandCollection, and how do you make your own type work in afor-inloop?// Sequence: an iterator with a mutating next() is all for-in needsstruct Countdown: Sequence { let start: Int func makeIterator() -> Iterator { Iterator(current: start) }…What is the difference between
#if,#availableand@availablein Swift?import Foundation#if canImport(UIKit)import UIKit // only where the SDK has UIKit#endif #if DEBUG…How do you use Objective-C code from Swift and Swift code from Objective-C in one target, and what cannot cross the boundary?
import Foundation // Visible to Objective-C through the generated "App-Swift.h"@objc class Logger: NSObject { @objc func log(_ message: String) { print(message) }}…What does this code print, and why does
maprun more often than you might expect?let numbers = [1, 2, 3, 4, 5, 6]let squares = numbers.lazy .map { n -> Int in print("map \(n)") return n * n } .filter { $0 % 2 == 0 } print("start")print(squares.first!)print(squares.first!)What is type erasure, and when do you still need a hand-written type eraser now that
any P<T>exists?protocol Repository<Item> { associatedtype Item: Identifiable func fetch(id: Item.ID) async throws -> Item} struct Order: Identifiable { let id: Int }…How does Swift run generic code, and why can an
anyparameter be slower than a generic one?What is a phantom type, and what kind of bug does it prevent?
struct ID<Tag>: Hashable, Codable, Sendable { let rawValue: String} enum UserTag {} // never instantiated: exists only as a typeenum OrderTag {}…What are typed throws (
throws(MyError)), and when should you use them instead of plainthrows?enum ParseError: Error { case empty case notANumber(String) case outOfRange(Int)}…Passing a big
Arrayaround in Swift looks free. How does copy-on-write work, and how would you implement it for your own type?final class Storage { // final and private to the struct var pixels: [UInt8] init(pixels: [UInt8]) { self.pixels = pixels } func copy() -> Storage { Storage(pixels: pixels) }}…Find the bug: clearing a copy of this
Playlistalso empties the original.struct Playlist { private final class Storage { var ids: [Int] init(ids: [Int]) { self.ids = ids } } private var storage = Storage(ids: []) var ids: [Int] { storage.ids } mutating func removeAll() { storage.ids.removeAll() } mutating func append(_ id: Int) { if !isKnownUniquelyReferenced(&storage) { storage = Storage(ids: storage.ids) } storage.ids.append(id) } mutating func insert(_ id: Int, at index: Int) { if !isKnownUniquelyReferenced(&storage) { storage = Storage(ids: storage.ids) } storage.ids.insert(id, at: index) }}How does Swift implement
weakandunownedunder the hood (side tables, three reference counts), and why can an object's memory outlive itsdeinit?final class Session { let name: String init(name: String) { self.name = name } deinit { print("deinit \(name)") }}…You need a wrapper for a raw file descriptor that cannot be copied, closed twice or used after closing. What does
~Copyablegive you?import Darwin struct FileDescriptor: ~Copyable { private let fd: Int32 init?(opening path: String) {…When do you write a macro instead of a property wrapper, and why is
@Observablea macro?import Foundationimport Observation @Observablefinal class CartModel { var items: [String] = []…