Skip to content

Instantly share code, notes, and snippets.

@brennanMKE
Created April 5, 2025 08:13
Show Gist options
  • Save brennanMKE/439ca53b590818dd5901d615befdca54 to your computer and use it in GitHub Desktop.
Save brennanMKE/439ca53b590818dd5901d615befdca54 to your computer and use it in GitHub Desktop.
Swift Study Notes

✅ Swift 6 Study Notes — any, some, Existentials, Boxing, Dispatch

(via ChatGPT)

🧱 any vs some — Existential vs Opaque Types

any Protocol

  • Existential type: Can hold a value of any type that conforms to the protocol.
  • Requires heap allocation (boxing).
  • Uses dynamic dispatch via a witness table.
  • Used when you need flexibility (e.g. heterogeneous collections, dynamic polymorphism).

Example:

let x: any View = Text("Hello")

some Protocol

  • Opaque return type: Compiler knows the exact concrete type, caller does not.
  • Uses static dispatch — fast and inlineable.
  • Only allowed in return position, not as parameter or variable types.
  • Used for performance, especially in SwiftUI.

Example:

var body: some View {
  Text("Hello")
}

🧠 What is an Existential?

An existential is a runtime value of an unknown concrete type that conforms to a protocol. You get an existential when using any Protocol.

Key Properties:

  • Value is boxed in heap memory.
  • Supports dynamic dispatch via witness table.
  • Type-erased: concrete type information is not available at compile time.

📦 What is Boxing?

Boxing wraps a value in a heap-allocated container so it can be treated as an existential.

When does it happen?

  • When using any Protocol (e.g. any Error, any View, any Hashable)
  • When returning from a function or storing as a property

Overheads:

  • Heap allocation (slower than stack)
  • Reference counting
  • Dynamic dispatch (no inlining)
  • Pointer indirection

🚫 Swift does not allow the box to point to a value on the stack — it must be copied to the heap for safety.


⚡ Dispatch — Static vs Dynamic

Dispatch Type Triggered By Speed Inlineable Example
Static Concrete types, some, generics ✅ Fast ✅ Yes let x = Text("Hi")
Dynamic any, protocols, classes ❌ Slower ❌ No let x: any View = Text("Hi")

🧠 What is a Witness Table?

A witness table is a structure Swift generates to map protocol requirements to the concrete type's implementations.

It’s used for:

  • Dynamic dispatch
  • Calling protocol methods on an any existential
  • Ensuring the type actually conforms to the protocol

Example:

protocol Animal { func speak() }

struct Dog: Animal {
  func speak() { print("Woof") }
}

let pet: any Animal = Dog()
pet.speak() // uses witness table for Dog:Animal

🧩 Protocol Extensions and Dispatch

  • Methods declared in the protocol = dynamically dispatched when using any.
  • Methods only in the extension = statically dispatched, even for any.

Example:

protocol Animal {
  func greet()
}

extension Animal {
  func greet() { print("Hello from protocol") }
  func wag() { print("Default wag") }
}

struct Dog: Animal {
  func greet() { print("Woof") }
  func wag() { print("Custom wag") }
}

let dog: any Animal = Dog()
dog.greet() // Woof — dynamic
dog.wag()   // Default wag — static! (extension-only method)

To make wag() dynamically dispatched, you must declare it in the protocol.


🔖 Summary Cheat Sheet

Concept Use any Use some
Flexibility ✅ Can hold any conformer ❌ Only one concrete type
Performance ❌ Heap allocation, slower ✅ Fast, inlined
Type Safety ❌ Type-erased ✅ Known to compiler
Use In ✅ Variables, parameters ❌ Only return types
Dispatch ❌ Dynamic (witness table) ✅ Static
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment