Working with Structures
1. Defining Structures
| Property | Description | Example |
|---|---|---|
| struct Name { } | Defines a new structure | |
| 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 | |
| func method() | Instance method | |
| static func method() | Static method (on type, not instance) | |
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 | |
| Memberwise Initializer | Uses the struct's property names to initialize values | |
| Custom Initializer | Allows for custom logic during initialization | |
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 |
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 | |
| Mutating Methods | Methods that modify the structure's properties | |
| Type Methods | Methods that operate on the structure type itself, not instances | |
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 | |
| Immutability | Structures are value types and can be made immutable with let |
|
| Copy Behavior | When a structure is assigned to a new variable, it's a deep copy | |
| Mutability in Functions | Passing structures to functions creates copies, changes don't affect original | |
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