Recall drill — the named facts you missed

recall · drill

In one line: Cover the blue, say the answer aloud, uncover. Every line is a question you answered “I don’t know”, half-right, or backwards. ! = missed twice / headline gap. Exact names, numbers, lists — the reasoning you already have.

Download PDF Print view LaTeX source

=1.5mm! UIStackView — 4 properties → axis · distribution (sizing along axis) · alignment (across axis) · spacing

=1.5mmdistribution values → .fill (default) · .fillEqually · .fillProportionally · .equalSpacing · .equalCentering

=1.5mm! Priority values → .required = 1000 · .defaultHigh = 750 · .defaultLow = 250

=1.5mmContent hugging → resists growing past intrinsic size; default 250

=1.5mmCompression resistance → resists shrinking below intrinsic size (truncation); default 750

=1.5mmWho loses a tie? → the lower priority stretches/shrinks; nudge ±1 (749, 251) to decide

=1.5mm#1 cause: code view at 0/wrong place → forgot translatesAutoresizingMaskIntoConstraints = false

=1.5mmFacts per view → x, y, width, height — size may come from intrinsic content size

=1.5mmUnsatisfiable constraints → ≥2 contradictory required (1000) → engine breaks one arbitrarily + log; optional (<1000) breaks silently

=1.5mmSelf-sizing cells → rowHeight = .automaticDimension + non-zero estimatedRowHeight + unbroken top→bottom chain in contentView

=1.5mmSize classes → horizontal/vertical × .compact/.regular; iPhone portrait = compact W, regular H; iPad = regular/regular

=1.5mm! JSON user_name → userName → (1) enum CodingKeys: String, CodingKey { case userName = "user_name" } (per key) (2) decoder.keyDecodingStrategy = .convertFromSnakeCase (blanket) (3) custom init(from:)

=1.5mm! 3 error layers (Reach·Receive·Read) → URLError (transport) → HTTP statusCode not in 200..<300 (not thrown) → DecodingError (.keyNotFound/.typeMismatch/.dataCorrupted)

=1.5mm! dataTask completion thread → URLSession’s background queue, never main → DispatchQueue.main.async; call .resume()

=1.5mmasync/await data(from:) → resumes on the caller’s actor — @MainActor caller needs no hop

=1.5mmPinning delegate → urlSession(_:didReceive:completionHandler:) with URLAuthenticationChallenge → serverTrust → SecTrustEvaluateWithError → SPKI hash → .useCredential / .cancelAuthenticationChallenge. Default TLS validation: yes

=1.5mmVC order → loadView → viewDidLoad (once) → viewWillAppear → viewDidAppear → viewWillDisappear → viewDidDisappear

=1.5mmFrame valid from → viewWillLayoutSubviews — not viewDidLoad

=1.5mmApp states → Not Running → Inactive → Active ↔ Inactive → Background → Suspended

=1.5mm! 3 memory tools → Memory Graph Debugger (cycles: who retains whom) · Leaks (unreachable blocks) · Allocations (growth; Mark Generation)

=1.5mmweak vs unowned → weak: Optional, auto-nils, target may die first · unowned: non-optional, target outlives self, crash if touched after dealloc

=1.5mmDoes var x: C? break a cycle? → No — ? = nil-ability; weak/unowned = ownership

=1.5mmweak var delegate: P? needs → protocol P: AnyObject

=1.5mm! { [x] in print(x) }, then x = 20 → prints 10: capture list = by-value snapshot at creation. No list → captures the variable → 20. [obj] copies the pointer

=1.5mm! Copy-on-write → Array Dictionary Set String (+Data): struct wrapping class storage; isKnownUniquelyReferenced(&storage) — 1 → mutate in place, >1 → copy first. Your structs: no COW for free

=1.5mm! mutating → lets a struct/enum method change self; caller must be var; classes never need it; on a let struct → compile error

=1.5mmWhen must it be a class? → identity/shared state · inheritance · ObjC interop · deinit

=1.5mmUnit-test a leak → weak var ref; create SUT in inner scope; after scope XCTAssertNil(ref)

=1.5mmsome View → opaque type: compiler knows the concrete type; hidden from the caller

=1.5mm@StateObject vs @ObservedObject → view creates & owns (once) vs passed in; @ObservedObject var vm = VM() resets on parent re-render

=1.5mm@Binding → two-way ref to a parent’s @State, made with $; owns nothing

=1.5mmiOS 17 @Observable → owned → @State; injected → plain property

=1.5mm! Test pyramid → Unit 70% · Integration 20% · UI 10%; inverted = “ice-cream cone”

=1.5mm5 test doubles → Dummy (fills a slot) · Stub (canned answers) · Spy (stub + records calls) · Mock (pre-set expectations, self-verifies) · Fake (working simplified impl, e.g. in-memory)

=1.5mm#expect vs #require → soft (continues) vs hard (throws, stops)

=1.5mmXCTest per-test order → new instance → setUpWithError → setUp → test → teardown blocks (LIFO) → tearDownWithError → tearDown

=1.5mmLogic lives in (MVC / MVP / MVVM) → Controller / Presenter (View behind a protocol, no UIKit) / ViewModel (View binds, VM has no View ref)

=1.5mmFacade — what + risk → one simple interface over a subsystem (URLSession, Repository); risk: swells into a god object — delegate, don’t implement

=1.5mmAdapter — textbook iOS → UIViewRepresentable / UIHostingController (UIKit ↔ SwiftUI)

=1.5mmCoordinator solves → a VC that pushes its next screen knows its siblings → not reusable; VC signals intent, Coordinator navigates

=1.5mmRepository read → cache → miss → API → write back → return; caller never knows the source

=1.5mmDI vs DIP → DI = technique (pass deps in); DIP = principle (depend on abstractions)

=1.5mm! Singleton downsides → hidden dependencies · hard to test / state leaks · global mutable state · tight coupling (breaks DIP). Impl: static let shared (lazy, thread-safe) + private init

=1.5mm! Strategy vs State → Strategy: client picks the algorithm (stranger) · State: object transitions itself (self)

=1.5mm! Observer’s problem → leaks / retain cycles if not unsubscribed → AnyCancellable, store(in:), removeObserver

=1.5mm! Command → undo → execute() + undo() (captures state); undo stack: undo = pop, undo(), push to redo

=1.5mm! Proxy variants → Virtual · Protection · Remote · Caching (“Very Private Rooms Cache”); lazy var = virtual proxy

=1.5mmInterface: Adapter / Decorator / Facade / Proxy → changes it / keeps + adds behaviour / new simpler one / keeps + gates access

=1.5mm! Template Method → Hollywood principle: “don’t call us, we’ll call you” — base calls your hooks; e.g. UIViewController lifecycle

=1.5mm! Responder chain direction → up: first responder → superview → VC → window → UIApplication → app delegate. Hit-testing goes down

=1.5mmMediator → peers talk via a hub: N2 → N links (Coordinator, VM, UINavigationController)

=1.5mmFactory Method vs Abstract Factory → FM: subclass overrides to pick one product · AF: one object makes a family. create(type:) switch = Simple Factory

=1.5mm! Decorator vs subclass → N features → 2N subclasses vs N stackable wrappers; Swift: ViewModifier

=1.5mmBuilder → fixes telescoping init; Swift: default params; recipe object = Director

=1.5mmIterator in Swift → IteratorProtocol.next() -> Element? (nil = end) + Sequence.makeIterator()

=1.5mmStrategy serves → Open/Closed + Dependency Inversion (not ISP)

=1.5mmS → one, and only one, reason to change

=1.5mmO → open for extension, closed for modification

=1.5mmL → subtypes substitutable for their base types (Square:Rectangle breaks it)

=1.5mm! I → clients should not be forced to depend on methods they do not use

=1.5mm! D → high- and low-level modules both depend on abstractions; abstractions don’t depend on details

=1.5mmErrors → Reach, Receive, Read

=1.5mmTools → Graph = cycles · Leaks = unreachable · Allocations = growing

=1.5mmPriorities → 1000/750/250, spaced by 250 so ±1 breaks ties; 750 = “don’t shrink me”, 250 = “don’t stretch me”

=1.5mmCapture list → a photo: values freeze; references freeze the pointer

=1.5mmOwnership → weak/unowned change ownership; ? only changes nil-ability

=1.5mmStack view → axis = direction · distribution = along · alignment = across · spacing = gaps

=1.5mmAdapter · Decorator · Proxy → changes · adds · gates (a bouncer)