Blog / April 6, 2023 / 4 mins read / By Mahi Garg

Structs in Swift

When it comes to designing data structures in Swift, one of the fundamental building blocks you’ll encounter is the struct. A struct, short for structure, is a versatile and lightweight data type that allows you to encapsulate related properties and behaviors together. In this blog, we’ll delve into the world of structs in Swift, explore their features, benefits, and demonstrate how they can be used to create robust and maintainable code with practical examples.

What are Structs?

In Swift, a struct is a value type that enables you to define a blueprint for creating custom data types. It can include properties to store values and methods to perform actions related to those values. Unlike classes, structs are value types, meaning they are copied when passed around in code, rather than referenced. This behavior can have significant implications for your program’s memory management and can be very advantageous in certain scenarios.

Declaring Structs

Let’s start by creating a simple struct to represent a 2D point:

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

In this example, we’ve defined a struct called Point with two properties: x and y, both of type Double. Now, we can create instances of this struct to represent specific points:

var origin = Point(x: 0.0, y: 0.0)
var pointA = Point(x: 3.5, y: 2.0)

Accessing Struct Properties

You can access the properties of a struct using dot notation:

print("The x-coordinate of point A is \(pointA.x)")
print("The y-coordinate of point A is \(pointA.y)")

Struct Methods

Structs can also have methods, just like classes. Let’s add a method to our Point struct to calculate the distance between two points:

struct Point {
    var x: Double
    var y: Double
    
    func distance(to otherPoint: Point) -> Double {
        let xDistance = self.x - otherPoint.x
        let yDistance = self.y - otherPoint.y
        return (xDistance * xDistance + yDistance * yDistance).squareRoot()
    }
}

Using Struct Methods

let pointB = Point(x: 5.0, y: 4.0)
let distance = pointA.distance(to: pointB)
print("The distance between point A and point B is \(distance)")

Mutating Methods

If you want a method to modify the struct’s properties, you’ll need to mark the method as mutating. Let’s add a method to our Point struct that moves the point by a given offset:

struct Point {
    var x: Double
    var y: Double
    
    mutating func moveBy(x deltaX: Double, y deltaY: Double) {
        x += deltaX
        y += deltaY
    }
}

Using Mutating Methods

var pointC = Point(x: 1.0, y: 1.0)
print("Point C before moving: (\(pointC.x), \(pointC.y))")

pointC.moveBy(x: 2.5, y: 3.5)
print("Point C after moving: (\(pointC.x), \(pointC.y))")

Structs and Immutability

Unlike classes, which are reference types, structs are value types and have inherent immutability. This means that by default, you cannot modify the properties of a struct instance declared as a constant (using let). To make a struct mutable, you need to use the mutating keyword with methods that modify its properties, as shown in the previous example.

Practical Use Case: Currency Conversion

Let’s consider a practical use case for a struct. We’ll create a CurrencyConverter struct that holds the exchange rates for different currencies and provides a method to convert amounts between them:

struct CurrencyConverter {
    var exchangeRates: [String: Double]  // e.g., ["USD": 1.0, "EUR": 0.85, "JPY": 109.5]
    
    func convert(amount: Double, from sourceCurrency: String, to targetCurrency: String) -> Double? {
        guard let sourceRate = exchangeRates[sourceCurrency], let targetRate = exchangeRates[targetCurrency] else {
            return nil
        }
        return amount * (targetRate / sourceRate)
    }
}

Using CurrencyConverter

let converter = CurrencyConverter(exchangeRates: ["USD": 1.0, "EUR": 0.85, "JPY": 109.5])
let amountInUSD = 100.0

if let amountInEUR = converter.convert(amount: amountInUSD, from: "USD", to: "EUR") {
    print("\(amountInUSD) USD is equal to \(amountInEUR) EUR.")
} else {
    print("Currency conversion failed.")
}

Conclusion

Structs are a powerful tool in Swift for building lightweight, flexible, and maintainable data types. They allow you to encapsulate related data and behavior, promote immutability by default, and can be particularly useful when working with value semantics or scenarios where copy-on-write behavior is desirable. By understanding the nuances of structs and incorporating them into your Swift code, you can make your applications more efficient, organized, and robust.

In this blog, we’ve covered the basics of structs and demonstrated how to create, use, and benefit from them in your Swift projects. Whether you’re working on iOS apps, macOS applications, or server-side projects, structs will undoubtedly play a significant role in improving your code quality and overall development experience.

So, the next time you find yourself in need of a lightweight, value-based data structure, think of structs as your go-to choice for building clean and elegant solutions! Happy coding! 🚀

Comments