Swift Variables (var) and Constants (let) Explained
Swift uses variables and constants to store values in your program. This topic is one of the first things every Swift developer learns, because almost every piece of code depends on naming data, reading it later, and deciding whether that value should be allowed to change. In this article, you will learn what var and let mean, how to declare them, when to use each one, and how to avoid the most common beginner mistakes.
Quick answer: In Swift, use var to create a variable whose value can change, and use let to create a constant whose value cannot be reassigned after it is set. In most cases, prefer let by default and switch to var only when you truly need mutability.
Difficulty: Beginner
Helpful to know first: You will understand this better if you already know basic Swift syntax, how to print values, and simple types such as String, Int, and Bool.
1. What Is Variables (var) & Constants (let)?
A variable or constant gives a name to a value so your program can use it later. Instead of writing the same literal value everywhere, you store it once and refer to it by name.
- var creates a stored value that can be changed later.
- let creates a stored value that cannot be reassigned after initialization.
- Both help make code more readable by replacing raw values with meaningful names.
- Swift encourages safe code, so constants are preferred whenever possible.
- The main comparison is simple: let means immutable binding, while var means mutable binding.
For example, a user's name usually stays the same during a short function, so it can often be declared with let. A score in a game changes over time, so it should usually be declared with var.
2. Why Variables (var) & Constants (let) Matters
Choosing between var and let affects correctness, readability, and safety.
When you use let, Swift protects that value from accidental reassignment. This reduces bugs, especially in longer functions where values pass through several steps. A constant also communicates intent to other developers: this value is meant to stay fixed.
When you use var, you allow a value to evolve. This is useful for counters, user input, temporary state, and calculations that happen in stages.
In real projects, using the right one matters because:
- It prevents unintended changes to important values.
- It makes code easier to reason about during debugging.
- It helps the compiler enforce safer patterns.
- It signals whether a value is part of changing state or fixed configuration.
A helpful rule is: if you are not sure whether a value should change, start with let. If Swift later shows that reassignment is necessary, change it to var.
3. Basic Syntax or Core Idea
The syntax for declaring a variable or constant is simple. You write the keyword, then a name, then optionally a type annotation, and then a value.
Declaring a constant with let
Use let when the value should stay the same after it is assigned.
let siteName = "DevDocs10"
print(siteName)
This creates a constant named siteName. Swift infers that its type is String from the assigned value.
Declaring a variable with var
Use var when the value needs to change.
var score = 0
score = 10
print(score)
This works because score was declared as a variable, so Swift allows reassignment.
Adding an explicit type
You can also write the type yourself. This is useful when clarity matters or when the initial value does not make the intended type obvious.
let maxUsers: Int = 100
var temperature: Double = 21.5
Here, the type annotation comes after the name and before the value.
Declaring first and assigning later
Swift also allows declaration without an immediate value if the type is known and the value will be set before use.
var username: String
username = "Taylor"
print(username)
This is valid because the variable has a type and gets a value before it is read.
4. Step-by-Step Examples
Example 1: Storing a fixed app name
An app name usually does not change while the program runs, so a constant is a good fit.
let appName = "WeatherNow"
print("App: \(" + appName + ")")
This example shows a constant used for configuration-style data that should remain unchanged.
Example 2: Updating a counter
Counters change over time, so they should be variables.
var pageViews = 0
pageViews += 1
pageViews += 1
print(pageViews)
The value starts at 0 and changes as visits are counted.
Example 3: Using type annotations for clarity
Sometimes adding the type makes your intent clearer to the reader.
let pi: Double = 3.14159
var cartItems: Int = 2
print(pi)
print(cartItems)
This is especially useful in tutorial code, APIs, and places where inferred types may be less obvious.
Example 4: Declaring a value and assigning it later
You may know the type before you know the exact value.
var message: String
message = "Welcome back!"
print(message)
This is common when a value depends on later logic, user input, or a function result.
5. Practical Use Cases
- Use let for fixed configuration values such as app names, API base URLs, and tax rates that should not be reassigned.
- Use var for counters, scores, totals, and values that are updated inside loops.
- Use let for function-local values that are calculated once and then reused.
- Use var for form input, current selections, or state that changes in response to user actions.
- Use let to make important values safer when passing them through multiple lines of logic.
- Use var when building a value step by step, such as accumulating a total price or building a status message.
6. Common Mistakes
Mistake 1: Trying to reassign a constant
A constant declared with let can only be assigned once. After that, Swift does not allow a new value.
Problem: This code tries to change a constant after initialization, so Swift reports an error such as Cannot assign to value: 'name' is a 'let' constant.
let name = "Ana"
name = "Mila"
Fix: Use var only if the value is meant to change.
var name = "Ana"
name = "Mila"
The corrected version works because var allows reassignment.
Mistake 2: Declaring without enough type information
Swift needs to know the type of a variable or constant. If you do not provide a value or a type annotation, Swift cannot infer what the storage should hold.
Problem: This declaration does not include a value or a type, so Swift cannot infer the intended type and reports an error.
var total
Fix: Either assign an initial value or provide an explicit type annotation.
var total = 0
var price: Double
The corrected version works because Swift now knows what type each variable should store.
Mistake 3: Reading a variable before assigning a value
If you declare a variable with a type but no initial value, you must assign something before using it.
Problem: This code attempts to read greeting before it has been initialized, which causes a compile-time error.
var greeting: String
print(greeting)
Fix: Assign a value before the first read.
var greeting: String
greeting = "Hello"
print(greeting)
The corrected version works because the variable is initialized before it is used.
Mistake 4: Using var when let communicates intent better
Not every value that could be mutable should be mutable. Overusing var makes code harder to reason about.
Problem: This code marks a fixed value as mutable, which can lead to accidental reassignment later and makes the code less clear.
var countryCode = "US"
print(countryCode)
Fix: Use let when the value should stay constant.
let countryCode = "US"
print(countryCode)
The corrected version communicates more clearly that the value is fixed.
7. Best Practices
Practice 1: Default to let
A common Swift style is to start with let and change to var only when needed. This makes your intent safer and clearer.
Less preferred:
var username = "Casey"
Preferred:
let username = "Casey"
This practice reduces accidental changes and better documents your code.
Practice 2: Choose descriptive names
The name of a variable or constant should tell the reader what the value means, not just that a value exists.
Less preferred:
let x = 30
Preferred:
let maxLoginAttempts = 30
Descriptive names make maintenance easier and reduce the need for extra comments.
Practice 3: Add explicit types when they improve clarity
Swift type inference is powerful, but an explicit type can make code easier to read in APIs, shared code, or educational examples.
Less preferred when the intended type is not obvious:
let timeout = 5
Preferred when you want to show intent clearly:
let timeoutSeconds: Double = 5.0
This helps other developers understand the expected kind of value immediately.
8. Limitations and Edge Cases
- A let constant cannot be reassigned, but that does not mean every nested piece of data is always deeply immutable in every scenario. The exact behavior depends on the type and whether it exposes mutable internal state.
- Swift must know a variable's type either from the assigned value or from an explicit annotation. A declaration with neither will fail to compile.
- A variable declared without an initial value cannot be used until it has been initialized.
- Type inference is convenient, but sometimes integer and floating-point values can behave differently than beginners expect. For example, 5 is inferred as Int, while 5.0 is inferred as Double.
- If you see a message like Cannot assign to value: 'x' is a 'let' constant, the problem is reassignment, not the original declaration syntax.
- If a value truly needs to change across steps of a calculation, forcing it into let will make the code awkward. In those cases, var is the correct choice.
9. Practical Mini Project
Let’s build a small checkout summary that uses both constants and variables. Constants hold fixed values such as product name and shipping fee. Variables hold values that change, such as quantity and total cost.
let productName = "Notebook"
let unitPrice: Double = 4.50
let shippingFee: Double = 2.00
var quantity = 2
var subtotal = Double(quantity) * unitPrice
var total = subtotal + shippingFee
print("Product: \(productName)")
print("Quantity: \(quantity)")
print("Subtotal: \(subtotal)")
print("Total: \(total)")
// Customer adds one more notebook
quantity = 3
subtotal = Double(quantity) * unitPrice
total = subtotal + shippingFee
print("Updated quantity: \(quantity)")
print("Updated total: \(total)")
This example shows a realistic pattern: fixed values are constants, while values that react to user behavior are variables. That makes the code easier to read and safer to maintain.
10. Key Points
- var creates a value that can be reassigned later.
- let creates a value that cannot be reassigned after initialization.
- Prefer let by default and switch to var only when change is required.
- Swift can often infer types, but explicit annotations are useful when they improve clarity.
- A variable declared without an initial value must be assigned before it is read.
- The error Cannot assign to value: is a 'let' constant means you tried to change a constant.
11. Practice Exercise
Create a small program for tracking a user's reading progress.
- Declare a constant for the book title.
- Declare a constant for the total number of pages.
- Declare a variable for the current page and set it to an initial value.
- Update the current page after the user reads more pages.
- Print the book title, total pages, current page, and remaining pages.
Expected output: The program should show fixed book information and an updated reading position after the page value changes.
Hint: Use let for values that do not change and var for the page number that updates.
let bookTitle = "Swift Basics"
let totalPages = 250
var currentPage = 40
print("Book: \(bookTitle)")
print("Total pages: \(totalPages)")
print("Current page: \(currentPage)")
print("Remaining pages: \(totalPages - currentPage)")
currentPage = 85
print("Updated current page: \(currentPage)")
print("Updated remaining pages: \(totalPages - currentPage)")
12. Final Summary
Variables and constants are foundational in Swift because they control how your program stores and manages data. The key distinction is simple: use let for values that should not change, and use var for values that must change over time. That one decision improves safety, readability, and correctness throughout your code.
In this article, you learned the core syntax, saw how type inference and type annotations work, explored practical examples, fixed common errors, and applied the concept in a small mini project. If you want to continue building your Swift basics, a strong next step is learning Swift data types such as String, Int, Double, and Bool, because variables and constants become much more useful once you understand the kinds of values they can store.