Let and var in Swift explained

Published on: July 12, 2024
Updated on: July 7, 2025

Virtually every programming language will have some means to define properties; Swift does too. We have two approaches to defining a property in Swift. We can use a var or a let. The code below shows how we can define a var or a let as a member of a class:

class Member {
  let id: UUID
  var name: String

  init(name: String) {
    self.id = UUID()
    self.name = name
  }
}

This class has two properties. One is a let, the other is a var.

If you're coming from a Javascript background you might expect that there's a third option here; const. That's not the case in Swift. Swift only has let and var and a let in Swift might not be what you think it is. We'll start by exploring var a little bit more before we dig into let and how it's not the same as a let in JavaScript.

Understanding variables in Swift

A var property is a variable. That means that whatever we assign to the var can change over time. For example, when I make an instance of my Member object, I can change the name as needed:

var instance = Member(name: "Donny")
instance.name = "Hello, world!"

And because I defined instance as a var, I'm even able to create a new Member and assign it to my instance variable:

var instance = Member(name: "Donny")
instance.name = "Hello, world!"

instance = Member(name: "Oliver")

We also refer to a var as being mutable. This is another way of saying that the value for this property can change.

A let is the opposite of a var in that sense. Let's take a look at that next.

Defining let properties in Swift

A let in Swift is considered a constant value. This means that once we've assigned a value to our let, we can't change it. Let's dig in some more.

For example, if I define my instance as a let instead of a var I'm no longer allowed to assign a new value to instance:

// notice how intstance is now defined as a let
let instance = Member(name: "Donny")
instance.name = "Hello, world!"

instance = Member(name: "Oliver") // not allowed, instance is a let

Additionally, because my Member defined id as a let, I can't change that either:

let instance = Member(name: "Donny")
instance.id = UUID() // not allowed, id is a let

I can, however still change the name:

let instance = Member(name: "Donny")
instance.name = "Hello, world!"

That's because changing a property on my class instance will propagate as a change to let instance. The class instance assigned to let instance is still the exact same one. We just changed one of the properties.

When should you choose let instead of var?

As is often case in programming, there's a simple answer to this question and a complex one. The simple answer would be to always use let instead of var. An immutable program is easier to reason about than a mutable program, so defining as much of your properties as you can as constants is often a good idea.

That said, for properties defined on structs it doesn't matter as much. You can define immutable data on structs as let but ultimately the mutability of a struct's properties will depend on how that struct is used. Let's take a close look at the nuances of using let and var on structs next.

Let and var nuances when using structs

The rules around var and let change a bit when we make Member a struct:

struct Member {
  let id: UUID
  var name: String

  init(name: String) {
    self.id = UUID()
    self.name = name
  }
}

The properties on Member are the exact same. The only difference is that we've made Member a struct instead of a class.

I won't expand into the difference between structs and classes too much in this post, but it's important to understand that a class is assigned to a variable(var) or constant(let) using its address in memory. So instead of storing the actual class value in our property, we only store the location of our class instance. That's why changing a value on our instance doesn't re-assign to our let instance in the example above.

Structs on the other hand are generally stored by value. This means that when you change a property on a struct, Swift will have to re-assign the new value to the property that's storing your instance. Let's see this in action:

let instance = Member(name: "Donny")
instance.name = "Hello, world!" // this is not allowed because `instance` is immutable

What's happening in the code above is that we've assigned a value to let instance. When we change the name of our instance, Swift has to replace the old value of instance with a new one because it's a struct and structs are stored using their values.

To allow mutating our instance.name, we have to store the instance as a var:

var instance = Member(name: "Donny")
instance.name = "Hello, world!" // this is allowed because `instance` is a variable

Now Swift is able to make a copy of our Member with the updated name and then assign it back to var instance.

In Summary

We generally like to write our code using let instead of var whenever we can. The fewer properties we can change, the more predictable our code becomes, and the fewer bugs we'll ship. However, a program that never changes any of its properties wouldn't be very interesting because it'd just be a static page. So in those situations where you do need the ability to re-assign or update a property it makes sense to define that property as a var. When in doubt, use let. Then change it to a var when you find that you do have a need to update that specific property later on.

Expand your learning with my books

Practical Swift Concurrency header image

Learn everything you need to know about Swift Concurrency and how you can use it in your projects with Practical Swift Concurrency. It contains:

  • Eleven chapters worth of content.
  • Sample projects that use the code shown in the chapters.
  • Free updates for future iOS versions.

The book is available as a digital download for just $39.99!

Learn more