Skip to main content

Command Palette

Search for a command to run...

Swift Value & Reference

Updated
4 min readView as Markdown
Swift Value & Reference

Value Types vs. Reference Types

In Swift, types are split into two categories: value types and reference types. They behave differently, and knowing how they work is key to writing smooth, bug-free code.

To paint a picture, imagine you're working on a document, and you want to share it with a friend. There are two ways to do this:

  1. Send a copy of the document.

  2. Send a link to the document, like a shared Google Doc.

In both cases, your friend can see and edit the document, but there’s a big difference:

  • With the copy, any changes your friend makes don’t affect your version.

  • With the link, both of you are editing the same document, so whatever changes they make are immediately reflected on your side too.

This difference is exactly like value types and reference types in Swift.


Every Copy is Independent

In Swift, things like structures, enumerations, and tuples are value types. They’re like sending a copy of a document—every time you assign them to a new variable or pass them into a function, you're making a copy.

Take this example with a struct:

struct Document {
    var text: String
}

var myDoc = Document(text: "Great new article")
var friendDoc = myDoc  // Makes a copy of myDoc

friendDoc.text = "Blah blah blah"
print(friendDoc.text)  // Prints "Blah blah blah"
print(myDoc.text)      // Still prints "Great new article"

Here, changing friendDoc doesn’t affect myDoc. They’re totally separate after the assignment. So, with value types, you're the only one controlling changes to your copy, making things predictable and easy to follow.


Everyone Shares the Same Instance

Now, let’s talk reference types, like classes, actors, and closures. These are like sending a link to a shared document. When you assign a reference type, you’re just creating another reference to the same object.

Check out this class-based version:

class Document {
    var text: String
}

var myDoc = Document(text: "Great new article")
var friendDoc = myDoc  // Points to the same instance

friendDoc.text = "Blah blah blah"
print(friendDoc.text)  // Prints "Blah blah blah"
print(myDoc.text)      // Also prints "Blah blah blah"

This time, myDoc and friendDoc both refer to the same object, so any change to one affects the other. This can be super handy, but also risky because changes can happen in unexpected places.


Keeping Things Predictable

When working with value types, you can reason about the code locally—what you see is what you get. No need to worry about something far away in your code making sneaky changes. This makes your code easier to understand and debug.

With reference types, though, you lose this local reasoning. If multiple parts of your program hold a reference to the same instance, any of them can change it, potentially causing hard-to-track bugs. This is called shared mutable state.


Choosing Value or Reference Types

So, when do you pick value types (like structs) over reference types (like classes)?

It’s all about what you need:

  • Value types are great for keeping things isolated. You know for sure that no one else is messing with your data behind the scenes. It’s simpler and safer when you don’t need shared state.

  • Reference types shine when you do need shared state, like when multiple parts of your app need to work with the same data. Just be aware of the added complexity!

As a general rule, prefer structs over classes unless you really need reference behavior.


Building Blocks for Bigger Things

You can combine value types to build bigger, more complex types. For example, a struct can hold other value types like String, Int, or even other structs. Since everything inside is a value type, the whole thing still behaves like a value type.

Here’s an example:

struct Report {
    var title: String
    var pageCount: Int
}

struct Library {
    var reports: [Report]
}

Here, even though Library is more complex, it still acts like a value type. This makes it predictable and safe from accidental changes elsewhere in your code.


Collections Are Value Types, Too!

In many programming languages, collections like arrays and dictionaries are reference types. But in Swift, Array, Dictionary, and Set are all value types. So, even if you have a struct that holds an array of values, everything still behaves as a value type, with copies being made when needed.


Wrapping It Up

Understanding the difference between value and reference types helps you keep control over your data. It boils down to whether you want your data to be copied (value types) or shared (reference types).

In Swift, when in doubt, go with structs unless you have a good reason to use a class. It’ll make your code easier to understand and less prone to tricky bugs.

And there you go! Now you’ve got a clear idea of how value and reference types work in Swift—and how to make the right choice for your code.

Programming

Part 7 of 17

Articles and tutorials about programming and computer science concepts.

Up next

How To Create An NFT On Bitcoin

(Clarity + Stacks) = (Bitcoin x Smart Contracts)

More from this blog

Damian Robinson | Online

20 posts

The blog and business site of Damian Robinson. You will find tutorials about programming and cybersecurity, and articles pertaining to various interests or pursuits of the author.