Value & Reference types in Swift

There are two categories a type in Swift can fall into:

  • Value Type
  • Reference Type

An instance of a Value type makes and keeps a unique copy of an original element. When the original element changes, the change does not affect the created copy. An instance of a Reference type, however, creates a reference, and it shares a single copy with the original element. This way, when the original element changes, it affects all the existing references.

  • Value types: Int, Double, String, Array, Dictionary, Set, Struct, Enum, Tuple
  • Reference types: Function, Closure, Class

Image description

Consider the following code block:

class Transport {
    var passengerCount = 10
}

let bus = Transport()
let car = bus

car.passengerCount = 4

print(bus.passengerCount) // 4
print(car.passengerCount) // 4

The class Transport has a stored property passengerCount, which has a default value of 10. We create a bus instance, and then the car instance, which make a reference to the original instance - bus. Once we change the property of car, that property is also changed for bus, and the reason for that is because class is a Reference type, meaning it works with references, and all the instances are affected.

Let's change that to a Struct:

struct Transport {
    var passengerCount = 10
}

let bus = Transport()
var car = bus

car.passengerCount = 4

print(bus.passengerCount) // 10
print(car.passengerCount) // 4

Now, when car was created, the compiler made a copy of bus, and those are two separate instances, we can modify them without any affect on each other. Notice how car is created as a variable, instead of a constant. The reason is simple - when we create a value type with let we make a constant, unable to change the stored properties.

Why would you prefer one over another?

Use a value type when:

  • You want to be able to compare instances with "==". A double equal operator (aka ==) compares values.
  • You want to have independent copies.
  • The data will be used in code across multiple threads. So that you don't have to worry about the data being changed from another thread.

Use a reference type (e.g. use a class) when:

  • You want to be able to compare instances with "===". The operator checks if two objects are exactly identical, right down to the memory address that stores the data.
  • You want to create shared, mutable state.
How Reference and Value types are stored in memory?

Value type is stored on Stack Memory. Reference type is stored on Managed Heap Memory.

Differences between Stack and Heap

Stack is used for static memory allocation and Heap for dynamic memory allocation, both stored in the computer's RAM. As mentioned earlier, reference type instances are stored in heap and instances of a value type such as struct resides in a region of memory called stack. If the value type instance is part of a class instance, the value is stored in the heap along with the class instance.

April 20, 2021