Reference vs. Value Types in Swift
Types in Swift broadly fall into categories, reference and value types. If you’re new to Swift, do yourself a favor by not following my example and learn about the differences between the two sooner rather than later. If you’re reading this now, then presumably it is sooner rather than later, relatively speaking, so congratulations! Let’s dive right in.
Value types, such as struct
, tuple
, and enum
, are the conceptually simpler. As the name implies, every instance holds its own unique copy of its properties and their values.
struct Statement { var isTrue: Bool = false } var a = Statement() var b = a // Copy a to b a.isTrue = true // Change a's instance print("The statement below is \(a.isTrue).") // The statement below is true. print("The statement above is \(b.isTrue).") // The statement above is false.
No robots were short-circuited in the making of this logical fallacy.
Reference types, namely class
, act like pointers in C/C++ without the peril of memory management (Ok, “peril” might be a strong word but you can really do some damage with raw pointers). Under the hood, copies of an instance of a reference type all share the same value in memory, and mutations to one copy are visible in every other one.
class Statement { var isTrue: Bool = false } var a = Statement() var b = a // Copy a to b a.isTrue = true // Change the underlying instance value print("The statement below is \(a.isTrue).") // The statement below is true. print("The statement above is \(b.isTrue).") // The statement above is true.
Swift prides itself on being simple, straight-forward, and above all, safe. Value types embody these ideas to a tee, as every instance is an island, immune to any unforeseeable side effects caused by mutating the data of a given copy. In fact, thanks to extensions and the protocol-oriented-programming nature of Swift, one could do without classes entirely, if not for the fact that so many Cocoa APIs expect to deal with NSObjects, and not value types.
With all of this in mind, it’s clear that value types are generally preferable, so when should we use a reference type instead? Aside from the previous example of class inheritance, reference types become necessary when implementing trees and other graph structures, as traversal, insertion, and deletion all require pointer objects that share the same memory as the nodes they refer to.
And there you have it! Reference and value types are subtle but important distinction to understand in the never-ending battle to write safe, predictable code.
References*
*Pun not intended (But I’m not complaining 🤷🏼♀️)