Skip to main content

Working with Structures

1. Defining Structures

Property Description Example
struct Name { } Defines a new structure
struct Person {
    var name: String
    var age: Int
}
var property: Type Mutable stored property var name: String = "John"
let property: Type Immutable stored property let id: Int
init(parameters) Initializer to set up properties
init(name: String, age: Int) {
    self.name = name
    self.age = age
}
func method() Instance method
func greet() {
    print("Hello, \(name)")
}
static func method() Static method (on type, not instance)
static func createDefault() -> Person {
    return Person(name: "Anonymous", age: 0)
}

Example: Basic Structure Definition

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)
    }
}
Note: Structures in Swift are value types, meaning they are copied when assigned or passed to functions.

2. Creating Structure Instances

Method Description Example
Default Initialization Creates an instance with default values for all properties
struct Person {
    var name: String = "Unknown"
    var age: Int = 0
}

let person1 = Person()
// Creates a Person with name = "Unknown" and age = 0
Memberwise Initializer Uses the struct's property names to initialize values
struct Point {
    var x: Double = 0.0
    var y: Double = 0.0
}

let point1 = Point(x: 5.0, y: 10.0)
// Creates a Point with x = 5.0 and y = 10.0
Custom Initializer Allows for custom logic during initialization
struct Rectangle {
    var width: Double
    var height: Double
    
    init(width: Double, height: Double) {
        self.width = width
        self.height = height
    }
}

let rect = Rectangle(width: 10.0, height: 5.0)
// Creates a Rectangle with width = 10.0 and height = 5.0

3. Using Memberwise Initializers

Memberwise initializers are automatically generated for structures in Swift. They allow you to initialize all properties of a structure with default values or specific values.

Property Type Description
name String Name of the person
age Int Age of the person
email String Email address of the person

Example: Initializing a Structure with Memberwise Initializer

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

let person = Person(name: "John Doe", age: 30, email: "john@example.com")

Example: Using Default Values in Memberwise Initializer

struct Person {
    var name: String = "Unknown"
    var age: Int = 0
    var email: String = "no-email@example.com"
}

let person = Person() // Uses default values

4. Adding Computed Properties

Property Type Description
computedProperty Int A read-only computed property that calculates its value based on other properties.
area Double Computed property that calculates the area of a rectangle.

Example: Calculating Area

struct Rectangle {
    var width: Double
    var height: Double
    
    var area: Double {
        return width * height
    }
}

let rect = Rectangle(width: 5.0, height: 3.0)
print(rect.area) // Output: 15.0

Example: Read-Only Property

struct Circle {
    var radius: Double
    
    var diameter: Double {
        return radius * 2
    }
}

let circle = Circle(radius: 4.0)
print(circle.diameter) // Output: 8.0

5. Adding Methods to Structures

Method Type Description Example
Instance Methods Functions that operate on an instance of the structure
struct Rectangle {
    var width: Double
    var height: Double

    func area() -> Double {
        return width * height
    }
}
Mutating Methods Methods that modify the structure's properties
struct Counter {
    var count = 0

    mutating func increment() {
        count += 1
    }
}
Type Methods Methods that operate on the structure type itself, not instances
struct MathUtils {
    static func square(_ number: Double) -> Double {
        return number * number
    }
}

Example: Using Instance Methods

struct Point {
    var x: Double
    var y: Double

    func distance(from other: Point) -> Double {
        let dx = x - other.x
        let dy = y - other.y
        return sqrt(dx * dx + dy * dy)
    }
}

let p1 = Point(x: 0, y: 0)
let p2 = Point(x: 3, y: 4)
print(p1.distance(from: p2)) // 5.0

Example: Using Mutating Methods

struct Temperature {
    var celsius: Double

    mutating func add(degrees: Double) {
        celsius += degrees
    }

    func inFahrenheit() -> Double {
        return (celsius * 9/5) + 32
    }
}

var temp = Temperature(celsius: 20)
temp.add(degrees: 5)
print(temp.inFahrenheit()) // 68.0

6. Using Mutating Methods

Mutating methods in Swift structures allow you to modify the properties of a structure instance directly, even when that instance is declared as let. This is a key feature for working with value types that need to be modified.

Method Description Usage
mutating func Declares a method that can modify the structure's properties mutating func updateValue(_ newValue: Int)

Example: Mutating Method in a Structure

struct Counter {
    var count = 0
    
    mutating func increment() {
        count += 1
    }
    
    mutating func increment(by amount: Int) {
        count += amount
    }
}

var counter = Counter()
counter.increment()
print(counter.count) // 1

counter.increment(by: 5)
print(counter.count) // 6
Note: The mutating keyword is required when a method needs to modify the structure's properties. Without it, Swift will throw an error if you try to change a property inside the method.

7. Understanding Value Semantics

Aspect Description Example
Definition Value types that are copied when assigned or passed to functions
var a = 5
var b = a // b is a copy of a
a = 10
print(b) // Outputs: 5
Immutability Structures are value types and can be made immutable with let
struct Point {
    let x: Int
    let y: Int
}
let point = Point(x: 3, y: 4)
// point.x = 5 // Error: Cannot assign to property: 'point' is a 'let' constant
Copy Behavior When a structure is assigned to a new variable, it's a deep copy
struct Rectangle {
    var width: Int
    var height: Int
}
var rect1 = Rectangle(width: 10, height: 20)
var rect2 = rect1 // rect2 is a copy of rect1
rect1.width = 30
print(rect2.width) // Outputs: 10
Mutability in Functions Passing structures to functions creates copies, changes don't affect original
struct Counter {
    var count: Int = 0
}
func increment(_ counter: inout Counter) {
    counter.count += 1
}
var myCounter = Counter(count: 5)
increment(&myCounter)
print(myCounter.count) // Outputs: 6
Note: Value semantics ensure that structures behave predictably and safely in Swift, preventing unintended side effects from shared state.

8. Implementing Custom Initializers

Initializer Type Description Usage
Convenience Initializer Provides a simplified way to create an instance of a structure. init(parameter: Type) { ... }
Designated Initializer Defines the primary way to initialize a structure's properties. init(parameter: Type) { ... }

Example: Custom Initializer

struct Person {
    var name: String
    var age: Int

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

let person = Person(name: "Alex", age: 30)

Example: Convenience Initializer

struct Rectangle {
    var width: Double
    var height: Double

    init(width: Double, height: Double) {
        self.width = width
        self.height = height
    }

    init(squareSize: Double) {
        self.width = squareSize
        self.height = squareSize
    }
}

let square = Rectangle(squareSize: 5.0)

9. Using Static Properties and Methods

Member Description Usage
static var Defines a static property that belongs to the type, not instances. struct Person { static var count = 0 }
static func Defines a static method that belongs to the type, not instances. struct Math { static func add(_ a: Int, _ b: Int) -> Int { return a + b } }

Example: Using Static Properties

struct Counter {
    static var count = 0
    
    init() {
        Counter.count += 1
    }
}

print(Counter.count) // 0
let c1 = Counter()
print(Counter.count) // 1
let c2 = Counter()
print(Counter.count) // 2

Example: Using Static Methods

struct Calculator {
    static func multiply(_ a: Int, _ b: Int) -> Int {
        return a * b
    }
}

let result = Calculator.multiply(5, 6)
print(result) // 30

10. Conforming to Protocols

Protocol Requirements Description
Equatable == and != Allows structures to be compared for equality.
Hashable hash(into:) Enables structures to be used in sets and as dictionary keys.
Comparable <, <=, >, >= Allows structures to be sorted.

Example: Conforming to Equatable

struct Person: Equatable {
    let name: String
    let age: Int
}

let person1 = Person(name: "Alice", age: 30)
let person2 = Person(name: "Bob", age: 25)

print(person1 == person2) // false

Example: Conforming to Hashable

struct Coordinates: Hashable {
    let x: Int
    let y: Int
}

let set = Set([Coordinates(x: 1, y: 2), Coordinates(x: 3, y: 4)])
print(set.count) // 2

Example: Conforming to Comparable

struct Temperature: Comparable {
    let celsius: Double
    
    static func < (lhs: Temperature, rhs: Temperature) -> Bool {
        lhs.celsius < rhs.celsius
    }
    
    static func == (lhs: Temperature, rhs: Temperature) -> Bool {
        lhs.celsius == rhs.celsius
    }
}

let temp1 = Temperature(celsius: 20.0)
let temp2 = Temperature(celsius: 25.0)

print(temp1 < temp2) // true

Was this article helpful?