Skip to content

cheatnotes/swift-cheatsheet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Swift Programming Cheatsheet

Master Swift with this all-in-one reference guide covering 25 essential topics: from basic syntax, variables, and control flow to advanced concepts like generics, concurrency, property wrappers, and result builders. Includes practical code examples for collections, protocols, error handling, memory management, and SwiftUI. Perfect for beginners learning iOS/macOS development and experienced developers needing quick syntax recall. Features async/await, actors, closures, and pattern matching. Your go-to Swift resource for faster, more efficient coding.

Table of Contents

  1. Basic Syntax
  2. Variables and Constants
  3. Data Types
  4. Operators
  5. Control Flow
  6. Functions
  7. Closures
  8. Optionals
  9. Collections
  10. Strings
  11. Classes and Structures
  12. Properties
  13. Methods
  14. Inheritance
  15. Protocols
  16. Extensions
  17. Generics
  18. Error Handling
  19. Concurrency
  20. Memory Management
  21. Access Control
  22. Pattern Matching
  23. Type Casting
  24. Property Wrappers
  25. Result Builders

1. Basic Syntax

// Comments
// Single line comment
/* Multi-line
   comment */

// Print to console
print("Hello, World!")

// String interpolation
let name = "John"
print("Hello, \(name)")

// Semicolons are optional
let a = 5; let b = 10  // Can use to separate statements

// Module import
import Foundation
import UIKit

2. Variables and Constants

// Constants (immutable)
let constant = 42
let pi = 3.14159

// Variables (mutable)
var variable = 10
variable = 20

// Type annotations
var explicitString: String = "Hello"
var explicitInt: Int = 42
var explicitDouble: Double = 3.14
var explicitBool: Bool = true

// Multiple declarations
var x = 1, y = 2, z = 3
let a = 1, b = 2, c = 3

// Type inference
let inferredString = "Type is String"
let inferredInt = 42
let inferredDouble = 3.14

3. Data Types

// Integers
let integer: Int = 42
let int8: Int8 = 127
let int16: Int16 = 32767
let int32: Int32 = 2147483647
let int64: Int64 = 9223372036854775807
let unsignedInt: UInt = 42

// Floating-point numbers
let double: Double = 3.14159265359  // 64-bit (preferred)
let float: Float = 3.14  // 32-bit

// Boolean
let bool: Bool = true

// Character
let character: Character = "A"
let emoji: Character = "😀"

// String
let string: String = "Hello, World!"

// Tuples
let tuple = (1, "Hello", true)
let namedTuple = (code: 200, message: "OK")
let (statusCode, statusMessage) = namedTuple
let (_, justMessage) = namedTuple  // Ignore first element

// Type aliases
typealias AudioSample = UInt16
var sample: AudioSample = 45

// Numeric literals
let decimal = 17
let binary = 0b10001  // 17
let octal = 0o21  // 17
let hexadecimal = 0x11  // 17
let scientific = 1.25e2  // 125.0
let padded = 000123  // 123
let formatted = 1_000_000  // 1000000

4. Operators

// Arithmetic operators
let sum = 5 + 3  // 8
let difference = 10 - 3  // 7
let product = 4 * 2  // 8
let quotient = 10 / 3  // 3
let remainder = 10 % 3  // 1
let negation = -5  // -5

// Compound assignment operators
var count = 5
count += 2  // count = 7
count -= 3  // count = 4
count *= 2  // count = 8
count /= 4  // count = 2

// Comparison operators
let isEqual = 5 == 5  // true
let isNotEqual = 5 != 3  // true
let isGreater = 10 > 5  // true
let isLess = 3 < 7  // true
let isGreaterOrEqual = 10 >= 10  // true
let isLessOrEqual = 5 <= 3  // false

// Logical operators
let and = true && false  // false
let or = true || false  // true
let not = !true  // false

// Ternary conditional operator
let value = 10
let result = value > 5 ? "Greater" : "Less"

// Nil-coalescing operator
let optionalName: String? = nil
let name = optionalName ?? "Default Name"

// Range operators
let closedRange = 1...5  // 1,2,3,4,5
let halfOpenRange = 1..<5  // 1,2,3,4
let oneSidedRange = ...5
let oneSidedRange2 = 2...
let array = [1, 2, 3, 4, 5]
let slice = array[2...]  // 3,4,5

// Identity operators (for reference types)
class MyClass {}
let object1 = MyClass()
let object2 = object1
let isSameObject = object1 === object2  // true
let isNotSameObject = object1 !== MyClass()  // true

5. Control Flow

// If statement
if condition {
    // code
} else if anotherCondition {
    // code
} else {
    // code
}

// Switch statement (no break needed, exhaustive)
switch value {
case 1:
    print("One")
case 2, 3:
    print("Two or Three")
case 4...10:
    print("Between 4 and 10")
default:
    print("Other")
}

// Switch where clause
switch number {
case let x where x % 2 == 0:
    print("\(x) is even")
default:
    print("Odd")
}

// For-in loops
for i in 0...5 {
    print(i)
}

let numbers = [1, 2, 3, 4, 5]
for number in numbers {
    print(number)
}

let dict = ["a": 1, "b": 2]
for (key, value) in dict {
    print("\(key): \(value)")
}

// Stride
for i in stride(from: 0, to: 10, by: 2) {
    print(i)  // 0, 2, 4, 6, 8
}

for i in stride(from: 0, through: 10, by: 2) {
    print(i)  // 0, 2, 4, 6, 8, 10
}

// While loop
while condition {
    // code
}

// Repeat-while loop
repeat {
    // code
} while condition

// Control transfer statements
continue  // Skip current iteration
break  // Exit loop
fallthrough  // Fall through to next switch case
return  // Exit function
throw  // Throw error

// Labeled statements
outerLoop: for i in 1...3 {
    for j in 1...3 {
        if i * j == 6 {
            break outerLoop
        }
    }
}

// Guard statement
guard condition else {
    // Exit early (must transfer control)
    return
}

6. Functions

// Basic function
func greet(person: String) -> String {
    return "Hello, \(person)!"
}

// Multiple parameters
func multiply(a: Int, b: Int) -> Int {
    return a * b
}

// No return value
func sayHello() {
    print("Hello!")
}
// Or
func sayHi() -> Void {
    print("Hi!")
}
// Or
func sayHey() -> () {
    print("Hey!")
}

// Multiple return values (tuple)
func minMax(array: [Int]) -> (min: Int, max: Int)? {
    guard let first = array.first else { return nil }
    var currentMin = first
    var currentMax = first
    for value in array {
        if value < currentMin {
            currentMin = value
        }
        if value > currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}

// Argument labels
func greet(person name: String, from hometown: String) {
    print("Hello \(name)! Glad you could visit from \(hometown).")
}
greet(person: "John", from: "New York")

// Omitting argument labels
func add(_ a: Int, _ b: Int) -> Int {
    return a + b
}
let sum = add(5, 3)

// Default parameter values
func greet(person: String, politely: Bool = true) -> String {
    if politely {
        return "Hello, \(person), how are you?"
    } else {
        return "Hey, \(person)!"
    }
}

// Variadic parameters
func sum(_ numbers: Int...) -> Int {
    return numbers.reduce(0, +)
}
let total = sum(1, 2, 3, 4, 5)  // 15

// In-out parameters
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temp = a
    a = b
    b = temp
}
var x = 5, y = 10
swapTwoInts(&x, &y)

// Function types
let mathFunction: (Int, Int) -> Int = add
var anotherMathFunction = multiply

// Nested functions
func outerFunction() -> Int {
    func innerFunction() -> Int {
        return 42
    }
    return innerFunction()
}

7. Closures

// Basic closure syntax
{ (parameters) -> ReturnType in
    statements
}

// Closure examples
let greet = { (name: String) -> String in
    return "Hello, \(name)!"
}

// Shorthand argument names
let numbers = [1, 2, 3, 4, 5]
let doubled = numbers.map { $0 * 2 }

// Trailing closure syntax
numbers.map { $0 * 2 }

// Capturing values
func makeIncrementer(incrementAmount: Int) -> () -> Int {
    var total = 0
    let incrementer: () -> Int = {
        total += incrementAmount
        return total
    }
    return incrementer
}

// Escaping closures
var completionHandlers: [() -> Void] = []
func functionWithEscapingClosure(completion: @escaping () -> Void) {
    completionHandlers.append(completion)
}

// Autoclosures
func serve(customer customerProvider: @autoclosure () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: "John")

// Common closure methods
let sorted = numbers.sorted(by: { $0 > $1 })
let filtered = numbers.filter { $0 > 3 }
let mapped = numbers.map { String($0) }
let reduced = numbers.reduce(0, +)
let flatMapped = numbers.flatMap { [$0, $0 * 2] }
let compactMapped = ["1", "2", "three"].compactMap { Int($0) }  // [1, 2]

8. Optionals

// Optional declaration
var optionalString: String? = "Hello"
var optionalInt: Int?
var implicitOptional: String! = "Implicitly unwrapped"

// Unwrapping methods

// 1. Force unwrapping (unsafe)
let forced = optionalString!

// 2. Optional binding (if let)
if let unwrapped = optionalString {
    print(unwrapped)
}

// 3. Optional binding (guard let)
func process(string: String?) {
    guard let unwrapped = string else {
        return
    }
    print(unwrapped)
}

// 4. Nil-coalescing operator
let value = optionalInt ?? 0

// 5. Optional chaining
class Person {
    var residence: Residence?
}
class Residence {
    var address: Address?
}
class Address {
    var street: String?
}
let person = Person()
let street = person.residence?.address?.street

// Optional chaining with methods
class Room {
    func printNumberOfRooms() {
        print("5 rooms")
    }
}
let room: Room? = Room()
room?.printNumberOfRooms()

// Optional map and flatMap
let optionalNumber: Int? = 5
let mapped = optionalNumber.map { $0 * 2 }  // Optional(10)
let flatMapped = optionalNumber.flatMap { $0 > 3 ? $0 : nil }  // Optional(5)

9. Collections

// Arrays
var fruits = ["Apple", "Banana", "Orange"]
let emptyArray: [String] = []
let emptyArray2 = [Int]()

// Array operations
fruits.append("Mango")
fruits += ["Grapes", "Pineapple"]
fruits.insert("Strawberry", at: 0)
fruits.remove(at: 1)
fruits.removeLast()
fruits[0] = "Green Apple"
let firstFruit = fruits.first
let lastFruit = fruits.last
let count = fruits.count
let isEmpty = fruits.isEmpty
let contains = fruits.contains("Apple")

// Array iteration
for fruit in fruits {
    print(fruit)
}

for (index, fruit) in fruits.enumerated() {
    print("\(index): \(fruit)")
}

// Useful array methods
let sorted = fruits.sorted()
let reversed = fruits.reversed()
let shuffled = fruits.shuffled()
let randomElement = fruits.randomElement()
let slice = fruits[1...3]

// Sets
var set: Set = [1, 2, 3, 4, 5]
set.insert(6)
set.remove(2)
let containsElement = set.contains(3)

// Set operations
let set1: Set = [1, 2, 3, 4]
let set2: Set = [3, 4, 5, 6]
let union = set1.union(set2)  // [1, 2, 3, 4, 5, 6]
let intersection = set1.intersection(set2)  // [3, 4]
let difference = set1.subtracting(set2)  // [1, 2]
let symmetricDifference = set1.symmetricDifference(set2)  // [1, 2, 5, 6]
let isSubset = set1.isSubset(of: set2)
let isSuperset = set1.isSuperset(of: set2)
let isDisjoint = set1.isDisjoint(with: set2)

// Dictionaries
var scores: [String: Int] = ["Alice": 95, "Bob": 87, "Charlie": 78]
let emptyDict: [String: Int] = [:]
let emptyDict2 = [String: Int]()

// Dictionary operations
scores["David"] = 92
scores["Alice"] = 100
scores.updateValue(88, forKey: "Bob")
scores.removeValue(forKey: "Charlie")
scores["Charlie"] = nil  // Also removes value

// Dictionary access
let aliceScore = scores["Alice"]  // Optional(100)
let aliceValue = scores["Alice", default: 0]  // 100
let count2 = scores.count
let keys = scores.keys
let values = scores.values

// Dictionary iteration
for (name, score) in scores {
    print("\(name): \(score)")
}

// Useful dictionary methods
let mappedValues = scores.mapValues { $0 + 5 }
let grouped = Dictionary(grouping: [1, 2, 3, 4, 5]) { $0 % 2 == 0 ? "even" : "odd" }
let merged = scores.merging(["Eve": 85]) { (current, _) in current }

10. Strings

// String creation
let string = "Hello, World!"
let multiline = """
This is a
multiline
string.
"""

// String properties
let count3 = string.count
let isEmpty2 = string.isEmpty
let lowercase = string.lowercased()
let uppercase = string.uppercased()
let capitalized = string.capitalized

// String interpolation
let name2 = "John"
let age = 30
let message = "\(name2) is \(age) years old"

// Character access
let firstChar = string.first  // Optional("H")
let lastChar = string.last  // Optional("!")
let startIndex = string.startIndex
let endIndex = string.endIndex
let index = string.index(string.startIndex, offsetBy: 7)
let char = string[index]  // "W"

// Substrings
let substring = string.prefix(5)  // "Hello"
let suffix = string.suffix(6)  // "World!"
let dropFirst = string.dropFirst(7)  // "World!"
let dropLast = string.dropLast(1)  // "Hello, World"

// Range-based substring
let range = string.index(string.startIndex, offsetBy: 7)..<string.endIndex
let sub = string[range]  // "World!"

// String modification
var greeting = "Hello"
greeting.append(", World!")
greeting += " How are you?"
greeting.insert("!", at: greeting.startIndex)
greeting.insert(contentsOf: "Hey, ", at: greeting.startIndex)
greeting.remove(at: greeting.startIndex)

// String comparison
let equal = "hello" == "hello"
let hasPrefix = string.hasPrefix("Hello")
let hasSuffix = string.hasSuffix("!")
let contains2 = string.contains("World")

// String splitting
let words = "Hello, World, Swift".components(separatedBy: ", ")
let words2 = "Hello World Swift".split(separator: " ")

// String indices
for index in string.indices {
    print(string[index])
}

// Unicode
let emoji2 = "😀"
for scalar in string.unicodeScalars {
    print(scalar.value)
}

11. Classes and Structures

// Structure (value type)
struct Point {
    var x: Double
    var y: Double
    
    init(x: Double, y: Double) {
        self.x = x
        self.y = y
    }
    
    func distance(from point: Point) -> Double {
        let dx = x - point.x
        let dy = y - point.y
        return sqrt(dx * dx + dy * dy)
    }
}

// Class (reference type)
class Vehicle {
    var speed: Double = 0
    var description: String {
        return "Traveling at \(speed) mph"
    }
    
    func makeNoise() {
        // Do nothing
    }
}

// Initialization
let point = Point(x: 10, y: 20)
let vehicle = Vehicle()

// Memberwise initializer (auto-generated for structs)
let defaultPoint = Point(x: 0, y: 0)

// Designated vs Convenience initializers
class Food {
    var name: String
    
    init(name: String) {
        self.name = name
    }
    
    convenience init() {
        self.init(name: "[Unnamed]")
    }
}

// Failable initializers
struct Animal {
    let species: String
    
    init?(species: String) {
        if species.isEmpty { return nil }
        self.species = species
    }
}

// Required initializers
class SomeClass {
    required init() {
        // Must be implemented by subclasses
    }
}

// Deinitializers (classes only)
class FileManager {
    var filePath: String
    
    init(path: String) {
        self.filePath = path
    }
    
    deinit {
        print("Cleaning up \(filePath)")
    }
}

12. Properties

// Stored properties
struct Person {
    var firstName: String
    var lastName: String
    let id: Int  // Constant stored property
}

// Computed properties
struct Rectangle {
    var width: Double
    var height: Double
    
    var area: Double {
        get {
            return width * height
        }
    }
    
    var perimeter: Double {
        return 2 * (width + height)
    }
}

// Property observers
class StepCounter {
    var totalSteps: Int = 0 {
        willSet(newTotalSteps) {
            print("About to set totalSteps to \(newTotalSteps)")
        }
        didSet {
            if totalSteps > oldValue {
                print("Added \(totalSteps - oldValue) steps")
            }
        }
    }
}

// Lazy stored properties
class DataImporter {
    var filename = "data.txt"
}

class DataManager {
    lazy var importer = DataImporter()
    var data: [String] = []
}

// Type properties
struct SomeStructure {
    static var storedTypeProperty = "Some value"
    static var computedTypeProperty: Int {
        return 42
    }
}

class SomeClass2 {
    static var storedTypeProperty = "Some value"
    class var overrideableComputedTypeProperty: Int {
        return 42
    }
}

// Accessing type properties
let value1 = SomeStructure.storedTypeProperty
SomeStructure.storedTypeProperty = "New value"

13. Methods

// Instance methods
class Counter {
    var count = 0
    
    func increment() {
        count += 1
    }
    
    func increment(by amount: Int) {
        count += amount
    }
    
    func reset() {
        count = 0
    }
}

let counter = Counter()
counter.increment()
counter.increment(by: 5)

// Self property
struct Point2 {
    var x = 0.0, y = 0.0
    
    func isToTheRight(of x: Double) -> Bool {
        return self.x > x  // self disambiguates
    }
}

// Mutating methods (structs and enums)
struct Point3 {
    var x = 0.0, y = 0.0
    
    mutating func moveBy(x deltaX: Double, y deltaY: Double) {
        x += deltaX
        y += deltaY
    }
    
    mutating func moveTo(x: Double, y: Double) {
        self = Point3(x: x, y: y)
    }
}

// Type methods
class SomeClass3 {
    class func someTypeMethod() {
        print("Type method called")
    }
    
    static func anotherTypeMethod() {
        print("Static type method")
    }
}

SomeClass3.someTypeMethod()

14. Inheritance

// Base class
class Vehicle2 {
    var currentSpeed = 0.0
    var description: String {
        return "Traveling at \(currentSpeed) mph"
    }
    
    func makeNoise() {
        print("Vehicle noise")
    }
}

// Subclass
class Bicycle: Vehicle2 {
    var hasBasket = false
    
    override func makeNoise() {
        print("Ring ring")
    }
    
    override var description: String {
        return super.description + " on a bicycle"
    }
}

// Preventing overrides
final class FinalClass {
    // Cannot be subclassed
}

class Parent {
    final func cannotOverride() {
        // Cannot be overridden
    }
}

// Required initializers
class Vehicle3 {
    var speed: Double
    
    required init(speed: Double) {
        self.speed = speed
    }
}

class Car: Vehicle3 {
    required init(speed: Double) {
        super.init(speed: speed)
    }
}

15. Protocols

// Protocol definition
protocol FullyNamed {
    var fullName: String { get }
    func introduce() -> String
}

// Protocol adoption
struct Person2: FullyNamed {
    var fullName: String
    
    func introduce() -> String {
        return "Hi, I'm \(fullName)"
    }
}

// Protocol with mutating methods
protocol Togglable {
    mutating func toggle()
}

enum OnOffSwitch: Togglable {
    case on, off
    
    mutating func toggle() {
        switch self {
        case .on:
            self = .off
        case .off:
            self = .on
        }
    }
}

// Protocol inheritance
protocol TextRepresentable {
    var textualDescription: String { get }
}

protocol PrettyTextRepresentable: TextRepresentable {
    var prettyTextualDescription: String { get }
}

// Class-only protocols
protocol ClassOnly: AnyObject {
    // Only classes can adopt this
}

// Protocol composition
protocol Named {
    var name: String { get }
}

protocol Aged {
    var age: Int { get }
}

func wishHappyBirthday(to celebrator: Named & Aged) {
    print("Happy birthday, \(celebrator.name), you're \(celebrator.age)!")
}

// Optional protocol requirements
@objc protocol CounterDataSource {
    @objc optional func increment(forCount count: Int) -> Int
    @objc optional var fixedIncrement: Int { get }
}

// Protocol extensions
extension FullyNamed {
    func introduce() -> String {
        return "Hello, I'm \(fullName)"
    }
}

// Conditional conformance
extension Array: TextRepresentable where Element: TextRepresentable {
    var textualDescription: String {
        let itemsAsText = self.map { $0.textualDescription }
        return "[" + itemsAsText.joined(separator: ", ") + "]"
    }
}

16. Extensions

// Extension syntax
extension SomeType {
    // Add functionality here
}

// Computed properties
extension Double {
    var km: Double { return self * 1000.0 }
    var m: Double { return self }
    var cm: Double { return self / 100.0 }
    var mm: Double { return self / 1000.0 }
}

let distance = 5.km  // 5000.0

// Methods
extension Int {
    func repetitions(task: () -> Void) {
        for _ in 0..<self {
            task()
        }
    }
}

3.repetitions { print("Hello") }

// Mutating instance methods
extension Int {
    mutating func square() {
        self = self * self
    }
}

var number = 3
number.square()  // number is 9

// Subscripts
extension Int {
    subscript(digitIndex: Int) -> Int {
        var decimalBase = 1
        for _ in 0..<digitIndex {
            decimalBase *= 10
        }
        return (self / decimalBase) % 10
    }
}

746381295[0]  // 5
746381295[1]  // 9

// Nested types
extension Int {
    enum Kind {
        case negative, zero, positive
    }
    
    var kind: Kind {
        switch self {
        case 0:
            return .zero
        case let x where x > 0:
            return .positive
        default:
            return .negative
        }
    }
}

// Initializers
struct Size {
    var width = 0.0, height = 0.0
}

struct Point4 {
    var x = 0.0, y = 0.0
}

extension Rect {
    init(center: Point4, size: Size) {
        let originX = center.x - (size.width / 2)
        let originY = center.y - (size.height / 2)
        self.init(origin: Point4(x: originX, y: originY), size: size)
    }
}

17. Generics

// Generic functions
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
    let temp = a
    a = b
    b = temp
}

var a = 5, b = 10
swapTwoValues(&a, &b)

// Generic types
struct Stack<Element> {
    var items: [Element] = []
    
    mutating func push(_ item: Element) {
        items.append(item)
    }
    
    mutating func pop() -> Element? {
        return items.popLast()
    }
}

var stack = Stack<Int>()
stack.push(1)
stack.push(2)
let top = stack.pop()

// Type constraints
func findIndex<T: Equatable>(of valueToFind: T, in array: [T]) -> Int? {
    for (index, value) in array.enumerated() {
        if value == valueToFind {
            return index
        }
    }
    return nil
}

// Associated types
protocol Container {
    associatedtype Item
    mutating func append(_ item: Item)
    var count: Int { get }
    subscript(i: Int) -> Item { get }
}

// Generic where clauses
func allItemsMatch<C1: Container, C2: Container>(
    _ someContainer: C1, _ anotherContainer: C2
) -> Bool where C1.Item == C2.Item, C1.Item: Equatable {
    if someContainer.count != anotherContainer.count {
        return false
    }
    
    for i in 0..<someContainer.count {
        if someContainer[i] != anotherContainer[i] {
            return false
        }
    }
    return true
}

// Extensions with generic where clause
extension Stack where Element: Equatable {
    func isTop(_ item: Element) -> Bool {
        guard let topItem = items.last else {
            return false
        }
        return topItem == item
    }
}

// Generic subscripts
extension Container {
    subscript<Indices: Sequence>(indices: Indices) -> [Item]
        where Indices.Iterator.Element == Int {
        var result: [Item] = []
        for index in indices {
            result.append(self[index])
        }
        return result
    }
}

18. Error Handling

// Error types
enum VendingMachineError: Error {
    case invalidSelection
    case insufficientFunds(coinsNeeded: Int)
    case outOfStock
}

// Throwing functions
func canThrowError() throws -> String {
    // This function may throw
    return "Success"
}

func vend(itemName: String) throws {
    guard itemName == "Chips" else {
        throw VendingMachineError.invalidSelection
    }
    
    guard itemName.count > 0 else {
        throw VendingMachineError.outOfStock
    }
    
    throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
}

// Do-catch
do {
    try vend(itemName: "Candy")
} catch VendingMachineError.invalidSelection {
    print("Invalid selection")
} catch VendingMachineError.insufficientFunds(let coinsNeeded) {
    print("Need \(coinsNeeded) more coins")
} catch {
    print("Unexpected error: \(error)")
}

// Converting error to optional
let result = try? vend(itemName: "Chips")  // Returns optional
if let value = result {
    print(value)
}

// Disabling error propagation
let forcedResult = try! vend(itemName: "Chips")  // Crashes if error

// Rethrowing functions
func execute(_ closure: () throws -> Void) rethrows {
    try closure()
}

// Defer statement
func processFile() {
    defer {
        print("Closing file")
    }
    print("Opening file")
    print("Processing file")
    // File closes automatically
}

// Result type
enum NetworkError: Error {
    case badURL
    case noData
}

func fetchData(from url: String, completion: (Result<String, Error>) -> Void) {
    // Implementation
    completion(.success("Data"))
    // or
    completion(.failure(NetworkError.noData))
}

// Handling Result
fetchData(from: "https://example.com") { result in
    switch result {
    case .success(let data):
        print("Got data: \(data)")
    case .failure(let error):
        print("Error: \(error)")
    }
}

19. Concurrency

// Async/Await (Swift 5.5+)
func fetchUser() async throws -> String {
    // Simulate network call
    try await Task.sleep(nanoseconds: 1_000_000_000)
    return "User data"
}

// Calling async functions
Task {
    do {
        let user = try await fetchUser()
        print(user)
    } catch {
        print("Error: \(error)")
    }
}

// Async sequences
func fetchNumbers() -> AsyncStream<Int> {
    AsyncStream { continuation in
        for i in 1...5 {
            continuation.yield(i)
        }
        continuation.finish()
    }
}

Task {
    for await number in fetchNumbers() {
        print(number)
    }
}

// Task groups
func fetchAllUsers() async throws -> [String] {
    try await withThrowingTaskGroup(of: String.self) { group in
        var users: [String] = []
        
        for _ in 1...3 {
            group.addTask {
                try await fetchUser()
            }
        }
        
        for try await user in group {
            users.append(user)
        }
        
        return users
    }
}

// Actors
actor Counter2 {
    private var value = 0
    
    func increment() {
        value += 1
    }
    
    func getValue() -> Int {
        return value
    }
}

let counter2 = Counter2()
Task {
    await counter2.increment()
    let value = await counter2.getValue()
}

// Main actor
@MainActor
class ViewModel {
    var data: String = ""
    
    func updateData() async {
        data = await fetchData()
    }
    
    func fetchData() async -> String {
        return "Updated"
    }
}

// Sendable protocol
struct UserData: Sendable {
    let id: Int
    let name: String
}

// Task cancellation
let task = Task {
    try await longRunningOperation()
}

task.cancel()  // Cancel the task

func longRunningOperation() async throws {
    try Task.checkCancellation()  // Check for cancellation
    // Or
    if Task.isCancelled {
        return
    }
}

// Structured concurrency
func parentTask() async {
    async let child1 = fetchUser()
    async let child2 = fetchUser()
    
    let (result1, result2) = await (child1, child2)
    print(result1, result2)
}

20. Memory Management

// Automatic Reference Counting (ARC)
class Person3 {
    let name: String
    var apartment: Apartment?
    
    init(name: String) {
        self.name = name
        print("\(name) is being initialized")
    }
    
    deinit {
        print("\(name) is being deinitialized")
    }
}

// Strong reference cycles
class Apartment {
    let unit: String
    var tenant: Person3?  // Strong reference
    
    init(unit: String) {
        self.unit = unit
    }
}

// Weak references (avoid retain cycles)
class Person4 {
    let name: String
    var apartment: Apartment2?
    
    init(name: String) {
        self.name = name
    }
}

class Apartment2 {
    let unit: String
    weak var tenant: Person4?  // Weak reference
    
    init(unit: String) {
        self.unit = unit
    }
}

// Unowned references
class Customer {
    let name: String
    var card: CreditCard?
    
    init(name: String) {
        self.name = name
    }
}

class CreditCard {
    let number: UInt64
    unowned let customer: Customer  // Unowned reference
    
    init(number: UInt64, customer: Customer) {
        self.number = number
        self.customer = customer
    }
}

// Closure capture lists
class SomeClass4 {
    var closure: (() -> Void)?
    var value = 10
    
    func setupClosure() {
        // Capture list to break retain cycle
        closure = { [weak self] in
            guard let self = self else { return }
            print(self.value)
        }
        
        // Or with unowned
        closure = { [unowned self] in
            print(self.value)
        }
    }
}

21. Access Control

// Access levels
open class OpenClass { }  // Accessible and subclassable everywhere
public class PublicClass { }  // Accessible everywhere, subclassable only in module
internal class InternalClass { }  // Default - accessible within module
fileprivate class FilePrivateClass { }  // Accessible within file only
private class PrivateClass { }  // Accessible within enclosing declaration

// Properties
class MyClass2 {
    private var privateProperty = 0
    fileprivate var filePrivateProperty = 0
    internal var internalProperty = 0
    public var publicProperty = 0
    open var openProperty = 0
    
    private(set) var readOnlyProperty = 0  // Read-only from outside
}

// Extensions and access control
extension MyClass2 {
    // Can access private properties in same file
    func modifyProperties() {
        privateProperty = 10
        filePrivateProperty = 20
    }
}

// Subclassing restrictions
public class PublicBase {
    open func openMethod() { }
    public func publicMethod() { }
    internal func internalMethod() { }
    fileprivate func filePrivateMethod() { }
    private func privateMethod() { }
}

22. Pattern Matching

// Switch with patterns
let point5 = (2, 0)

switch point5 {
case (0, 0):
    print("Origin")
case (_, 0):
    print("On x-axis")
case (0, _):
    print("On y-axis")
case (-2...2, -2...2):
    print("Inside the box")
default:
    print("Outside the box")
}

// Value bindings
switch point5 {
case (let x, 0):
    print("On x-axis at \(x)")
case (0, let y):
    print("On y-axis at \(y)")
case let (x, y):
    print("At (\(x), \(y))")
}

// Where clause
switch point5 {
case let (x, y) where x == y:
    print("On the line x == y")
case let (x, y) where x == -y:
    print("On the line x == -y")
case (_, _):
    print("Just some point")
}

// If case
let optionalValue: Int? = 5
if case let value? = optionalValue {
    print("Has value: \(value)")
}

// For case
let array2: [Any] = [1, "Hello", 2, "World"]
for case let string as String in array2 {
    print("String: \(string)")
}

// Enum pattern matching
enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

let barcode = Barcode.qrCode("ABCDEFG")

switch barcode {
case .upc(let numberSystem, let manufacturer, let product, let check):
    print("UPC: \(numberSystem)")
case .qrCode(let productCode):
    print("QR: \(productCode)")
}

// Guard case
func extractValue(from optional: Int?) {
    guard case let value? = optional else {
        print("No value")
        return
    }
    print(value)
}

// Expression pattern
let point6 = (1, 2)

switch point6 {
case (0...5, 0...5):
    print("Inside")
default:
    print("Outside")
}

// Custom pattern matching with ~=
struct Point7 {
    var x: Int, y: Int
}

func ~= (pattern: String, value: Point7) -> Bool {
    switch pattern {
    case "origin":
        return value.x == 0 && value.y == 0
    case "positive":
        return value.x > 0 && value.y > 0
    default:
        return false
    }
}

let point7 = Point7(x: 5, y: 10)
if point7 ~= "positive" {
    print("Positive point")
}

23. Type Casting

// Checking type
class MediaItem {
    var name: String
    init(name: String) { self.name = name }
}

class Movie: MediaItem {
    var director: String
    init(name: String, director: String) {
        self.director = director
        super.init(name: name)
    }
}

class Song2: MediaItem {
    var artist: String
    init(name: String, artist: String) {
        self.artist = artist
        super.init(name: name)
    }
}

// Type checking (is)
let mediaItem: MediaItem = Movie(name: "Inception", director: "Nolan")

if mediaItem is Movie {
    print("It's a movie")
}

// Downcasting (as? and as!)
let items: [MediaItem] = [
    Movie(name: "Inception", director: "Nolan"),
    Song2(name: "Imagine", artist: "John Lennon")
]

for item in items {
    if let movie = item as? Movie {
        print("Movie: \(movie.name), director: \(movie.director)")
    } else if let song = item as? Song2 {
        print("Song: \(song.name), artist: \(song.artist)")
    }
}

// Forced downcasting
let forcedMovie = items[0] as! Movie  // Use only when certain

// Upcasting (as)
let upcastedItem: MediaItem = movie as MediaItem

// Any and AnyObject
var things: [Any] = []
things.append(42)
things.append("Hello")
things.append(Movie(name: "The Matrix", director: "Wachowski"))

for thing in things {
    switch thing {
    case let intValue as Int:
        print("Integer: \(intValue)")
    case let stringValue as String:
        print("String: \(stringValue)")
    case let movieValue as Movie:
        print("Movie: \(movieValue.name)")
    default:
        print("Something else")
    }
}

24. Property Wrappers

// Property wrapper definition
@propertyWrapper
struct Clamped<Value: Comparable> {
    private var value: Value
    private let range: ClosedRange<Value>
    
    init(wrappedValue: Value, _ range: ClosedRange<Value>) {
        self.range = range
        self.value = min(max(wrappedValue, range.lowerBound), range.upperBound)
    }
    
    var wrappedValue: Value {
        get { return value }
        set { value = min(max(newValue, range.lowerBound), range.upperBound) }
    }
}

// Using property wrapper
struct Player {
    @Clamped(0...100) var health: Int = 100
}

var player = Player()
player.health = 150  // Clamped to 100
player.health = -10  // Clamped to 0

// Projected value
@propertyWrapper
struct UserDefaultsStorage<T> {
    let key: String
    let defaultValue: T
    
    var wrappedValue: T {
        get { UserDefaults.standard.object(forKey: key) as? T ?? defaultValue }
        set { UserDefaults.standard.set(newValue, forKey: key) }
    }
    
    var projectedValue: Self { return self }
}

struct Settings {
    @UserDefaultsStorage(key: "username", defaultValue: "Guest")
    var username: String
    
    func reset() {
        $username.store(defaultValue: "Guest")
    }
}

// Property wrapper with additional parameters
@propertyWrapper
struct Formatted {
    private var value: String
    private var format: (String) -> String
    
    init(wrappedValue: String, formatter: @escaping (String) -> String = { $0 }) {
        self.value = formatter(wrappedValue)
        self.format = formatter
    }
    
    var wrappedValue: String {
        get { value }
        set { value = format(newValue) }
    }
}

struct User {
    @Formatted { $0.capitalized }
    var name: String
    
    @Formatted { $0.trimmingCharacters(in: .whitespaces) }
    var email: String
}

25. Result Builders

// Result builder definition
@resultBuilder
struct HTMLBuilder {
    static func buildBlock(_ components: String...) -> String {
        return components.joined(separator: "\n")
    }
    
    static func buildOptional(_ component: String?) -> String {
        return component ?? ""
    }
    
    static func buildEither(first component: String) -> String {
        return component
    }
    
    static func buildEither(second component: String) -> String {
        return component
    }
    
    static func buildArray(_ components: [String]) -> String {
        return components.joined(separator: "\n")
    }
}

// Using result builder
@HTMLBuilder
func buildPage(title: String, content: String) -> String {
    "<html>"
    "<head>"
    "<title>\(title)</title>"
    "</head>"
    "<body>"
    "<h1>\(title)</h1>"
    "<p>\(content)</p>"
    "</body>"
    "</html>"
}

let page = buildPage(title: "Hello", content: "World")

// Conditional content
@HTMLBuilder
func buildConditional(showExtra: Bool) -> String {
    "<div>Main content</div>"
    if showExtra {
        "<div>Extra content</div>"
    }
}

// Loop support
@HTMLBuilder
func buildList(items: [String]) -> String {
    "<ul>"
    for item in items {
        "<li>\(item)</li>"
    }
    "</ul>"
}

// SwiftUI example
import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Hello, World!")
                .font(.title)
                .padding()
            
            HStack {
                Button("Click me") {
                    print("Button clicked")
                }
                Spacer()
                Text("SwiftUI")
            }
        }
    }
}

About

from basic syntax, variables, and control flow to advanced concepts like generics, concurrency, property wrappers, and result builders. Includes practical code examples for collections, protocols, error handling, memory management, and SwiftUI.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Generated from cheatnotes/cheatnotes