Structs are Swift's default building block; SwiftUI views and most model types are structs.
A struct groups related data and behavior: struct Point { var x: Double; var y: Double }. Swift generates a memberwise initializer, Point(x: 1, y: 2), as long as you don't write your own init in the main declaration.
Structs are value types. Assignment and passing copy the value, so each variable owns its data independently. This makes reasoning local: no other code can change your copy. Most of the standard library (Int, String, Array, Dictionary) is built from structs.
Methods are functions inside the type. A method that changes stored properties must be marked `mutating`, and can only be called on a var. Inside a method, self refers to the instance; you rarely need to write it.
If you declare an instance with let, all its properties become immutable, even those declared var.
Use static for type-level properties and methods: static let origin = Point(x: 0, y: 0).
Apple's guidance: start with a struct, and reach for a class only when you need identity (one shared instance that several parts of the program observe), inheritance, or Objective-C interop. Structs can still conform to protocols and gain behavior through extensions.
Conforming to Equatable or Hashable is usually automatic: just declare the conformance and the compiler synthesizes == and hash(into:).
Example
struct Point: Equatable {
var x: Double
var y: Double
static let origin = Point(x: 0, y: 0)
func distance(to other: Point) -> Double {
((x - other.x) * (x - other.x) + (y - other.y) * (y - other.y)).squareRoot()
}
mutating func move(dx: Double, dy: Double) {
x += dx; y += dy
}
}
var a = Point(x: 3, y: 4)
var b = a
b.move(dx: 1, dy: 0)
print(a.x, b.x) // 3.0 4.0
print(a.distance(to: .origin)) // 5.0
print(a == Point(x: 3, y: 4)) // true
let fixed = Point(x: 1, y: 1)
// fixed.move(dx: 1, dy: 1) // error: fixed is a let constantRemember
- Structs are copied on assignment — each variable owns its value
- Methods that modify properties need
mutating - Default to struct; use a class when you need identity or inheritance
Watch out for
- Adding a custom
initinside the struct body and losing the memberwise initializer — put it in an extension to keep both.