Labs ICT
โญ Pro Login

Structs

Creating your own data types.

Structs in Swift

Structs are value types โ€” when you assign a struct to a new variable, you get a copy of the data, not a reference to the same data. This makes structs safe and predictable. In Swift, structs are the preferred way to create custom types for most use cases.

struct Point {
    var x: Double
    var y: Double
}

let origin = Point(x: 0, y: 0)
print(origin.x) // 0.0
Try it Yourself ->

Properties and Methods

Structs can have properties (stored data) and methods (functions that operate on that data). Methods can read and modify the struct's properties, giving you a clean way to organize related behavior.

struct Rectangle {
    var width: Double
    var height: Double
    
    func area() -> Double {
        return width * height
    }
    
    func perimeter() -> Double {
        return 2 * (width + height)
    }
}

let rect = Rectangle(width: 10, height: 5)
print("Area: \(rect.area())")       // Area: 50.0
print("Perimeter: \(rect.perimeter())") // Perimeter: 30.0
Try it Yourself ->

Memberwise Initializer

Swift automatically generates a memberwise initializer for structs. This initializer lets you create an instance by passing values for each property in order. It's one of the conveniences that makes structs so easy to use.

struct User {
    var name: String
    var age: Int
    var email: String
}

// Swift generates this automatically
let user = User(name: "Alice", age: 30, email: "alice@example.com")
print(user.name) // Alice
Try it Yourself ->

Computed Properties

Computed properties don't actually store a value โ€” they calculate it on the fly. They're defined as functions but used like properties, which can make your code more readable and expressive.

struct Circle {
    var radius: Double
    
    var circumference: Double {
        return 2 * .pi * radius
    }
    
    var area: Double {
        return .pi * radius * radius
    }
}

let circle = Circle(radius: 5)
print("Circumference: \(circle.circumference)")
print("Area: \(circle.area)")
Try it Yourself ->

Property Observers

Property observers let you run code before or after a property's value changes. willSet runs right before the change, and didSet runs right after. They're great for reacting to changes without overriding the setter.

struct StepCounter {
    var totalSteps: Int = 0 {
        willSet {
            print("About to change to \(newValue)")
        }
        didSet {
            if totalSteps > oldValue {
                print("Added \(totalSteps - oldValue) steps")
            }
        }
    }
}

var counter = StepCounter()
counter.totalSteps = 200
// About to change to 200
// Added 200 steps
counter.totalSteps = 360
// About to change to 360
// Added 160 steps
Try it Yourself ->

Mutating Methods

By default, struct properties cannot be modified in methods because structs are value types. If you need to modify a property, you must mark the method as mutating. This makes it clear that the method will change the struct's state.

struct GameState {
    var score: Int = 0
    
    mutating func addPoints(_ points: Int) {
        score += points
    }
    
    mutating func reset() {
        score = 0
    }
}

var game = GameState()
game.addPoints(100)
print(game.score) // 100
game.reset()
print(game.score) // 0
Try it Yourself ->

๐Ÿงช Quick Quiz

What is the difference between a struct and a class?