Swift Structs and Classes¶
Structs and classes are blueprints for custom types in Swift. Apple recommends using structs by default. Classes are needed for reference semantics, inheritance, or when used with frameworks that require them (Core Data, @Observable).
Key Facts¶
- Structs are value types (copied on assignment), classes are reference types (shared)
- Apple recommends struct by default unless class-specific features are needed
mutatingkeyword required for struct methods that modify properties- Every SwiftUI view is a struct conforming to the
Viewprotocol finalclass cannot be subclassed (required by SwiftData's@Model)- Structs get a free memberwise initializer; classes require explicit
init selfrefers to the current instance inside methods
Patterns¶
Struct Definition¶
struct Dog {
var name: String
var age: Int
var furColor: String
}
// Auto-generated memberwise initializer
var myDog = Dog(name: "Fido", age: 7, furColor: "brown")
myDog.age = 8 // update property (requires var)
Methods on Structs¶
struct Puppy {
var name: String
var hunger: Int
func bark() {
print("\(name) says Woof!")
}
mutating func eat() { // mutating required to change properties
hunger -= 1
}
}
var myPuppy = Puppy(name: "Fido", hunger: 5)
myPuppy.eat() // hunger becomes 4
myPuppy.bark() // "Fido says Woof!"
Class Definition¶
class Car {
var year: Int = 2020
var color: String = "red"
}
let myCar = Car()
myCar.color = "blue" // OK: let prevents reassignment, not property changes
Stored vs Computed Properties¶
// Stored property - holds a value
var count = 0
let name = "Nick"
// Computed property - runs code to produce a value each time
var body: some View { // required by View protocol
Text("Hello")
}
// Computed property on custom type
var fullName: String {
"\(firstName) \(lastName)"
}
Protocols¶
// View protocol - every SwiftUI view conforms
struct ContentView: View {
var body: some View { // computed property required by protocol
Text("Hello, world!")
}
}
// Identifiable protocol - required for List/ForEach
class JournalEntry: Identifiable {
var id = UUID()
var title: String
// ...
}
// CaseIterable protocol - provides .allCases array
enum APType: String, CaseIterable {
case land, air, sea
}
APType.allCases // [.land, .air, .sea]
Conforming via Extension¶
Value Type vs Reference Type¶
// Struct (value type) - copies
var dog1 = Dog(name: "Fido", age: 3)
var dog2 = dog1 // dog2 is a COPY
dog2.name = "Buddy" // dog1.name still "Fido"
// Class (reference type) - shared
let car1 = Car()
let car2 = car1 // car2 points to SAME object
car2.color = "blue" // car1.color is also "blue"
Gotchas¶
- Forgetting
mutatingon struct methods that change properties causes a compile error leton a struct instance prevents ALL property changes;leton a class instance only prevents reassignment- SwiftUI views are structs, so properties cannot change without
@Stateor other property wrappers - Extensions cannot add stored properties - only computed properties and methods
some Viewis an opaque return type that hides the exact view type while conforming toView
See Also¶
- [[swift-fundamentals]] - variables, types, functions
- [[swift-enums-and-optionals]] - enums, optionals, switch
- [[swiftui-state-and-data-flow]] - @State enables mutation in struct-based views