Skip to main content

Swift Structures Basics

Introduction

Structures (or "structs") are one of the foundational building blocks in Swift programming. They allow you to create custom data types by grouping related values and behaviors together. Unlike classes in other languages, Swift structures are value types, making them particularly useful when you want to ensure data is copied rather than referenced.

In this tutorial, we'll explore the basics of Swift structures, how to define them, and how to use them effectively in your code. This knowledge forms an essential part of writing clean, efficient Swift applications.

What Are Structures?

A structure in Swift is a custom data type that encapsulates data and related functionality. Structures are particularly useful when you want to:

  • Group related properties and methods
  • Create immutable values
  • Ensure data is copied rather than referenced
  • Create reusable components with consistent behavior

Defining a Structure

Let's start by creating a simple structure:

swift
struct Person {
// Properties
var name: String
var age: Int

// Methods
func describe() -> String {
return "This person is \(name) who is \(age) years old."
}
}

This Person structure has:

  • Two properties: name (a String) and age (an Int)
  • One method: describe() that returns a String description of the person

Creating Instances of a Structure

Once you've defined a structure, you can create instances of it:

swift
// Create an instance of Person
let john = Person(name: "John", age: 25)

// Access properties
print(john.name) // Output: John
print(john.age) // Output: 25

// Call methods
print(john.describe()) // Output: This person is John who is 25 years old.

Notice that Swift automatically provides a memberwise initializer for structures, which allows you to create new instances by specifying values for each property.

Mutability in Structures

Structures in Swift are value types, which means they're copied when assigned to variables or passed as function arguments. This has important implications for mutability:

swift
struct Counter {
var count: Int = 0

mutating func increment() {
count += 1
}
}

// With a variable instance, you can modify properties
var counter1 = Counter()
counter1.count = 10
counter1.increment()
print(counter1.count) // Output: 11

// With a constant instance, you cannot modify properties
let counter2 = Counter()
// counter2.count = 10 // Error: Cannot assign to property
// counter2.increment() // Error: Cannot use mutating member on immutable value

Notice the mutating keyword before the increment() method. This is required for any method that changes properties within the structure.

Properties in Structures

Swift structures can have different types of properties:

Stored Properties

These are variables or constants stored as part of the structure:

swift
struct Rectangle {
var width: Double
var height: Double
}

Computed Properties

These are properties that calculate their value rather than storing it:

swift
struct Rectangle {
var width: Double
var height: Double

// Computed property
var area: Double {
return width * height
}
}

let rectangle = Rectangle(width: 10.0, height: 5.0)
print(rectangle.area) // Output: 50.0

Property Observers

These are blocks of code that execute when a property's value changes:

swift
struct Progress {
var task: String
var percentage: Double {
didSet {
print("\(task) is now \(percentage)% complete")
}
}
}

var progress = Progress(task: "Loading data", percentage: 0)
progress.percentage = 30 // Output: Loading data is now 30% complete
progress.percentage = 100 // Output: Loading data is now 100% complete

Custom Initializers

Although Swift provides a memberwise initializer automatically, you can define custom initializers:

swift
struct Temperature {
var celsius: Double

// Custom initializer
init(fahrenheit: Double) {
celsius = (fahrenheit - 32) / 1.8
}

// Another custom initializer
init(kelvin: Double) {
celsius = kelvin - 273.15
}
}

let temp1 = Temperature(celsius: 25)
let temp2 = Temperature(fahrenheit: 98.6)
let temp3 = Temperature(kelvin: 298.15)

print(temp1.celsius) // Output: 25.0
print(temp2.celsius) // Output: 37.0
print(temp3.celsius) // Output: 25.0

Practical Example: Building a Task Manager

Let's build a simple task management system using structures:

swift
struct Task {
var title: String
var isComplete: Bool = false

mutating func markComplete() {
isComplete = true
}
}

struct TaskList {
var name: String
var tasks: [Task] = []

mutating func add(task: Task) {
tasks.append(task)
}

mutating func completeTask(at index: Int) {
if index < tasks.count {
tasks[index].markComplete()
}
}

func printStatus() {
print("Task List: \(name)")
for (index, task) in tasks.enumerated() {
let status = task.isComplete ? "✓" : "□"
print("\(index + 1). [\(status)] \(task.title)")
}
}
}

// Usage example
var workTasks = TaskList(name: "Work Tasks")

workTasks.add(task: Task(title: "Finish Swift tutorial"))
workTasks.add(task: Task(title: "Prepare presentation"))
workTasks.add(task: Task(title: "Send weekly report"))

workTasks.printStatus()
// Output:
// Task List: Work Tasks
// 1. [□] Finish Swift tutorial
// 2. [□] Prepare presentation
// 3. [□] Send weekly report

workTasks.completeTask(at: 0)
workTasks.printStatus()
// Output:
// Task List: Work Tasks
// 1. [✓] Finish Swift tutorial
// 2. [□] Prepare presentation
// 3. [□] Send weekly report

This example shows how structures can be composed together to build a simple but effective system.

When to Use Structures

In Swift, you should prefer structures over classes when:

  1. You primarily need to encapsulate a few relatively simple data values
  2. You expect the encapsulated values to be copied rather than referenced
  3. Any properties stored by the structure are themselves value types
  4. You don't need inheritance from another type

Apple's guidance is to start with structures by default and only use classes when you specifically need reference semantics.

Summary

In this tutorial, we've covered the basics of Swift structures, including:

  • How to define structures with properties and methods
  • Creating and working with structure instances
  • Understanding mutability in structures
  • Different types of properties (stored, computed, and observers)
  • Custom initializers
  • A practical example building a task management system

Structures are a powerful feature in Swift that help you write safer, more predictable code. By understanding how to use them effectively, you're well on your way to becoming a proficient Swift programmer.

Additional Resources

Exercises

  1. Create a Book structure with properties for title, author, and pages. Add a method that returns whether the book is considered "long" (more than 300 pages).

  2. Design a BankAccount structure with properties for account number and balance. Add methods to deposit and withdraw money, ensuring the balance can't go below zero.

  3. Build a ShoppingCart structure that contains an array of Item structures. Implement methods to add items, remove items, and calculate the total price.

  4. Create a Point structure to represent a 2D point. Add a method to calculate the distance between two points.

  5. Implement a Temperature structure that can convert between Celsius, Fahrenheit, and Kelvin scales using computed properties.



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)