Irbisa · Cheatsheet
Swift Basics
Variables, optionals, types, control flow, closures, value vs reference
What is the difference between
letandvarin Swift?let name = "Ada"// name = "Grace" // error: cannot assign to a let constant var attempts = 0attempts += 1 // fine…What is an optional in Swift, how is it implemented, and how do you unwrap it safely?
var nickname: String? = "Ada" if let nickname { print(nickname.uppercased()) // runs only when there is a value}…What is the difference between
if letandguard let, and when do you reach forguard?struct User { let name: String; let isActive: Bool } func greet(_ user: User?) { guard let user, user.isActive else { print("nothing to greet") return // else has to leave the scope…What does this code print, and why does the first line show
Optional("Ada")?let name: String? = "Ada"let bonus: Int? = 5 print("Hello, \(name)")print("Hello, \(name ?? "guest")")print(bonus ?? 0 + 1)What is the difference between
String?andString!, and why does an@IBOutletdeclared asUILabel!crash with "unexpectedly found nil"?What is the difference between value types and reference types in Swift?
struct Point { var x: Int }let a = Point(x: 1)var b = a // an independent copyb.x = 99print(a.x) // 1…What is the difference between
==and===in Swift?struct Point: Equatable { var x: Int }print(Point(x: 1) == Point(x: 1)) // true: same content final class Box {}let a = Box()let b = Box()…What is the difference between
is,as,as?andas!?class Animal {}final class Dog: Animal { func bark() { print("woof") } } let pets: [Animal] = [Dog(), Animal()]for pet in pets { print(pet is Dog) // true, then false…What is the difference between
AnyandAnyObject?protocol Delegate: AnyObject {} // class-only protocol final class Screen { weak var delegate: Delegate? // weak needs a class-bound type}…What is the difference between
Array,SetandDictionary, and how do you choose between them?var tags = ["swift", "ios", "swift"]tags.insert("ui", at: 0) // O(n): shifts every element let unique = Set(tags) // 3 elements, order unspecifiedprint(unique.contains("ios")) // O(1) on average…What is the difference between
map,compactMapandflatMapin Swift?let raw: [String?] = ["swift", nil, "ios"]let lengths = raw.compactMap { $0?.count } // [5, 3]let withNils = raw.map { $0?.count } // [Int?]: 5, nil, 3 let numbers = ["1", "two", "3"].compactMap(Int.init) // [1, 3]let flat = [[1, 2], [3]].flatMap { $0 } // [1, 2, 3]…What can Swift's
switchdo that a C-styleswitchcannot?enum Download { case idle case running(progress: Double) case failed(retryIn: Int)}…Why can't you add an
Intto aDoublein Swift, and how doFloat,DoubleandCGFloatdiffer?let count = 7let total = 10// let ratio = count / total * 100.0 // error: Int and Double do not mixlet ratio = Double(count) / Double(total) * 100 // 70.0 let half = 1 / 2 // 0: both literals default to Int…What is a closure in Swift, and is it a value type or a reference type?
func makeCounter() -> () -> Int { var count = 0 return { // captures count and keeps it alive count += 1 return count }…What is the difference between
weakandunowned, and when do you need[weak self]in a closure?final class ProfileViewModel { var onUpdate: (() -> Void)? var title = "" func start() { // self owns onUpdate: capturing self strongly would be a retain cycle…How does error handling work in Swift:
throws,try,try?,try!,do/catchandResult?enum AuthError: Error { case invalidCredentials case throttled(retryAfter: Int)} struct User { let email: String }…What does this code print, and why does changing an element of the copy also change the original array?
final class Item { var title: String init(title: String) { self.title = title }} var original = [Item(title: "A"), Item(title: "B")]var copy = originalcopy[0].title = "Changed"copy.append(Item(title: "C")) print(original[0].title)print(original.count)Find the bug: tapping "Add" on a product that is already in the cart never increases its quantity.
struct CartItem { let name: String var quantity: Int} final class Cart { private(set) var items: [CartItem] = [] func add(_ name: String) { if var existing = items.first(where: { $0.name == name }) { existing.quantity += 1 } else { items.append(CartItem(name: name, quantity: 1)) } }}What does this code print, and what does the capture list
[value]change?func demo() { var value = 1 let captured = { print("captured:", value) } let copied = { [value] in print("capture list:", value) } value = 2 captured() copied()} demo()What does this code print, and when exactly does a
deferblock run?func demo() { var counter = 0 func next() -> Int { defer { counter += 1 } return counter } print(next(), counter)} func order() { defer { print("A") } defer { print("B") } print("C")} demo()order()What does
inoutdo, and how is it different from passing a class instance?func normalize(_ values: inout [Double]) { guard let maxValue = values.max(), maxValue > 0 else { return } for i in values.indices { values[i] /= maxValue }} var samples = [2.0, 4.0, 8.0]…Why can't you write
name[3]on a SwiftString, and what is aSubstring?let s = "Cafe\u{301}" // "Café": 5 scalars, 4 charactersprint(s.count) // 4print(s.unicodeScalars.count) // 5print(s == "Café") // true // let c = s[3] // error: no Int subscript…let rest = items.dropFirst()and thenrest[0]crashes with "Index out of bounds", althoughrestis not empty. Why?Three items at 1.10 add up to 3.3000000000000003 on a receipt. What went wrong, and what type should store money?
print(1.1 * 3) // 3.3000000000000003print(0.1 + 0.2 == 0.3) // falseprint(Int(4.35 * 100)) // 434, not 435 let priceCents = 110let totalCents = priceCents * 3 // 330, exact…What is the difference between
assert,preconditionandfatalError, and which of them still work in a Release build?assert(index >= 0, "negative index") // Debug only, not evaluated in Releaseprecondition(!items.isEmpty, "empty cart") // Debug and Release func make() -> Int { fatalError("unreachable") // returns Never, always traps}