Understanding Reference and Value Types in Swift

In this article, we’ll explore how memory allocation works for the main data types used in iOS development: reference types and value types. If you arrived here through the article Differences Between Class and Struct in Swift, get ready to deepen your knowledge, as we will now see how this works in practice.

When we declare an element in code, we are storing data at a specific memory address on the device, which can be accessed later. However, reference and value types handle this in different ways.

Reference Types
In Swift, the main reference types are classes, functions, and closures. Instances of these types store a reference to the memory address where the data is kept. This means that if multiple instances point to the same memory address, and one of them modifies the data, all others will reflect that change. We can observe this behavior in the example below:

				
					class Car {
    var brand: String

    init(brand: String) {
        self.brand = brand
    }
}
let car1 = Car(brand: "Ferrari")
let car2 = car1
car1.brand = "Mercedes"

print(car1.brand) /// Mercedes
print(car2.brand) /// Mercedes
print(car1 === car2) /// true
				
			

As shown in the example above, we should use reference types when we need instances that other instances can modify. To check whether two instances share the same reference, we can use the === operator, which returns true or false.

Value Types
The principal value types in Swift are structs, enums, and tuples. Instances of these types store copies of data at separate memory addresses. As a result, one instance cannot modify another’s data, and each instance manages its values independently. We can observe this behavior in the following example:

				
					struct Car {
    var brand: String

    init(brand: String) {
        self.brand = brand
    }
}
var car1 = Car(brand: "Ferrari")
var car2 = car1
car1.brand = "Mercedes"

print(car1.brand) /// Mercedes
print(car2.brand) /// Ferrari
print(car1.brand == car2.brand) /// false
				
			

As seen in the example above, we should use value types when we need instances that do not allow data modifications by other instances. To check if two instances hold the same values, we can use the == operator, which returns true or false.

Performance Considerations
It’s also worth noting that value-type instances are more performant since they do not require memory management resources like ARC (Automatic Reference Counting), which is necessary for reference types.

Understanding when to use reference or value types is crucial for optimizing memory management and ensuring efficient performance in Swift applications.

Enjoyed this article?

Connect with me on LinkedIn to stay updated with new posts. If you found this article helpful, feel free to share it!

More articles

Computer Science

Introduction to Processes and Threads

iOS, Swift

Differences Between Class and Struct in Swift

©2025 All rights reserved. Developed by Diego Montejano.