Irbisa · Cheatsheet
Swift OOP & Protocols
Classes, structs, enums, protocols, extensions, protocol-oriented programming
What is the difference between a struct and a class in Swift?
What are the main principles of OOP, and how does Swift express each one?
What is the difference between overloading and overriding, and what can a subclass override?
class Shape { var name: String { "shape" } func area() -> Double { 0 } final func describe() -> String { "\(name): \(area())" }}…What is a protocol in Swift, and how does it differ from an interface or an abstract class?
protocol Named { var name: String { get } // a let or a var satisfies it} protocol Greeter: Named { // protocol inheritance var greeting: String { get set } // needs something writable…What is the difference between raw values and associated values in a Swift enum?
enum HTTPStatus: Int { case ok = 200, notFound = 404}let status = HTTPStatus(rawValue: 404) // Optional(.notFound)print(HTTPStatus.ok.rawValue) // 200…What can an extension add to a type in Swift, and what can it not?
extension String { var isBlank: Bool { trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }} extension Array where Element: Numeric { // constrained extension func sum() -> Element { reduce(0, +) }…What access levels does Swift have, and what is the difference between
publicandopen?// Inside a framework moduleopen class BaseViewController { // apps may subclass and override open func configure() {}} public class Logger { // apps may use, not subclass…What is a
lazyproperty, how does it differ from a computed and an observed property, and can it be computed more than once?final class ProfileHeader { var name: String { willSet { print("about to show \(newValue)") } didSet { guard name != oldValue else { return } // observers fire even for equal values setNeedsLayout()…What does
mutatingdo, and why do struct methods need it while class methods do not?struct Counter { private(set) var value = 0 mutating func bump() { value += 1 }} enum Step {…What do
EquatableandHashablerequire, and what happens when two different values have the same hash?struct Tag: Hashable { // == and hash(into:) synthesized let name: String let colorHex: String} struct User: Hashable, Identifiable {…This delegate declaration does not compile. What is the error, and how do you fix it?
protocol DownloaderDelegate { func downloader(_ downloader: Downloader, didFinish text: String)} final class Downloader { weak var delegate: DownloaderDelegate? func finish(with text: String) { delegate?.downloader(self, didFinish: text) }}What is
deinit, when is it called, and on which thread does it run?final class ImageLoader { private var task: Task<Void, Never>? func start() { task = Task { /* download */ } } deinit {…What is the difference between
staticandclassmembers, and what doesfinalchange?class Formatter { static func make() -> Formatter { Formatter() } // cannot be overridden class var kind: String { "generic" } // subclasses may override // class var cache = 0 // error: class stored properties not supported}…How does class initialization work in Swift: designated vs convenience initializers, the two phases, and failable inits?
class Vehicle { let wheels: Int var name: String init(wheels: Int, name: String) { // designated: own properties, then up self.wheels = wheels…What is protocol-oriented programming, and how is it different from class inheritance?
protocol Loggable { var label: String { get } } extension Loggable { func log() { print(label) }}…What does this code print, and why do the two calls behave differently?
protocol Greeter { func greet() -> String} extension Greeter { func greet() -> String { "default greet" } func shout() -> String { "default shout" }}struct Robot: Greeter { func greet() -> String { "beep" } func shout() -> String { "BEEP" }} let robot: any Greeter = Robot()print(robot.greet())print(robot.shout())Can a Swift protocol have optional methods? Compare
@objc optionalwith a default implementation.@objc protocol ChartDataSource { func numberOfPoints() -> Int @objc optional func title() -> String // may be missing} final class SalesChart: NSObject, ChartDataSource {…Why does this struct not compile, and how would you model a linked list or a tree instead?
struct Node { let value: Int var next: Node?} var head = Node(value: 1, next: Node(value: 2, next: nil))When would you model variants with an enum with associated values, and when with a protocol and one type per variant?
Find the bug: after the 2.3 update, orders cached by the previous version show the wrong status.
enum OrderStatus: Int, Codable { case draft // added in 2.3 case paid case shipped case delivered} struct Order: Codable { let id: Int var status: OrderStatus} // Orders are cached on disk between launchesfunc loadCachedOrder(from data: Data) throws -> Order { try JSONDecoder().decode(Order.self, from: data)}Why must a non-final class mark the initializer that satisfies a protocol's
initrequirement asrequired?protocol Buildable { init(id: String)} class Node: Buildable { let id: String…How does method dispatch work in Swift (static, vtable, witness table and message dispatch), and what does each cost?
Find the bug: pull-to-refresh calls
refreshAll, but the feed screen never reloads.@MainActor protocol Refreshable: AnyObject { func refresh()}extension Refreshable { func refresh() {} // default: nothing to reload} class BaseViewController: UIViewController, Refreshable {} final class FeedViewController: BaseViewController { func refresh() { reloadFeed() }} @MainActor func refreshAll(_ screens: [any Refreshable]) { screens.forEach { $0.refresh() }}A type conforms to two protocols that each provide a default
refresh(). What does Swift do, and how do you resolve it?protocol Reloadable { func refresh() }protocol Pollable { func refresh() }extension Reloadable { func refresh() { print("from cache") } }extension Pollable { func refresh() { print("from network") } } struct Feed: Reloadable, Pollable {…