Welcome back, future Swift developer! In Chapter 1, we set up our development environment, which means we’re now ready to get our hands dirty and write some actual Swift code. This chapter is all about the fundamental building blocks of any program: how we store and manage information.

Think of programming as telling a story. To tell a story, you need characters, settings, and events. In programming, these “characters” and “settings” are often pieces of data—numbers, text, true/false values, and more. This chapter will introduce you to variables and constants, which are like named containers for this data, and basic data types, which define what kind of data those containers can hold. By the end of this chapter, you’ll be able to declare and use these essential elements to start bringing your ideas to life in Swift!

Ready to make some data dance? Let’s begin!

2.1 Storing Information: Variables and Constants

In Swift, you store data in named containers. These containers come in two main flavors: variables and constants. The key difference lies in whether the data they hold can change after you first assign it.

2.1.1 let: The Immutable Constant

Imagine you want to store a piece of information that will never change throughout your program’s execution, like the speed of light or a user’s birthdate. For these unchanging values, Swift gives us let.

What it is: A constant declared with let is a named container whose value, once set, cannot be changed. Why it’s important:

  • Safety: Prevents accidental modification of values that shouldn’t change, reducing bugs.
  • Clarity: Makes your code easier to read and understand, as it’s clear which values are fixed.
  • Performance: Swift can make optimizations knowing a value won’t change. How it functions: You declare it once, assign a value, and that’s it!

Let’s see it in action. Open up your Xcode Playground (or any Swift environment you prefer).

// Declare a constant for a person's name
let firstName = "Alice"

// Declare a constant for the maximum number of attempts allowed
let maxAttempts = 3

Observation:

  • Notice how we use the keyword let followed by the name we choose (firstName, maxAttempts), an equals sign (=), and then the value.
  • Swift is smart! It automatically figured out that "Alice" is text (a String) and 3 is a whole number (an Int). This is called type inference. We didn’t have to explicitly say let firstName: String = "Alice", though we could have.

Try it: What happens if you try to change firstName?

// Try to change the constant
// firstName = "Bob" // Uncomment this line and see the error!

You should see an error like “Cannot assign to value: ‘firstName’ is a ’let’ constant”. This is Swift protecting you, ensuring the immutability of your constant!

2.1.2 var: The Mutable Variable

Now, what if you need to store information that will change? For example, a player’s score in a game, or the current temperature. For these dynamic values, we use var.

What it is: A variable declared with var is a named container whose value can be changed after it’s initially set. Why it’s important: Essential for any data that needs to be updated, manipulated, or altered during your program’s execution. How it functions: You declare it, assign an initial value, and then you’re free to assign new values to it later.

Let’s look at an example:

// Declare a variable for a player's score
var playerScore = 0

// Declare a variable for a user's current city
var currentCity = "New York"

Observation:

  • Similar to let, we use var followed by the name, an equals sign, and the initial value.
  • Again, Swift uses type inference to determine playerScore is an Int and currentCity is a String.

Try it: Let’s update playerScore and currentCity.

// Update the player's score
playerScore = 100
print("Player Score: \(playerScore)") // Output: Player Score: 100

// Change the current city
currentCity = "San Francisco"
print("Current City: \(currentCity)") // Output: Current City: San Francisco

Notice how this time, Swift happily accepts the new values. This is the power of var!

2.1.3 When to Use let vs. var - A Golden Rule

Here’s a crucial best practice in Swift development:

Always prefer let over var unless you explicitly know the value needs to change.

Why? Because let makes your code safer, clearer, and potentially more performant. If you start with let and later realize you need to change the value, Xcode will give you a helpful suggestion to change it to var. It’s easier to loosen a restriction than to forget to add one.

2.2 Understanding Data Types

So far, we’ve seen Swift automatically infer types like String and Int. But what exactly are these types, and what other basic types are there? Swift is a type-safe language, meaning it’s very clear about what kind of data each variable or constant can hold. This helps prevent many common programming errors.

Let’s explore the fundamental data types you’ll use constantly.

2.2.1 Whole Numbers: Int

Int is used for whole numbers (integers), like 1, 100, -5, or 0.

What it is: Represents a whole number. Why it’s important: Used for counts, scores, ages, indices, and anything that doesn’t require a fractional part. How it functions: Stores positive or negative whole numbers. On a 64-bit system (like most modern iPhones and Macs), Int can store very large numbers. Swift also provides UInt for unsigned integers (positive-only), but Int is generally preferred for common use cases.

// Inferring Int
let age = 30

// Explicitly declaring Int
var numberOfStudents: Int = 25

// Large numbers
let populationOfCity = 1_000_000 // Underscores improve readability for large numbers

2.2.2 Decimal Numbers: Double and Float

For numbers with fractional components, like prices, measurements, or scientific calculations, we use floating-point types.

What they are: Represent numbers with decimal points. Why they’re important: Essential for calculations requiring precision. How they function:

  • Double: Represents a 64-bit floating-point number. It’s the default type for floating-point numbers in Swift when you don’t specify. It offers high precision and is generally preferred.
  • Float: Represents a 32-bit floating-point number. It has less precision than Double and is used less frequently unless memory conservation is critical.
// Inferring Double (default for decimals)
let price = 19.99

// Explicitly declaring Double
var pi: Double = 3.1415926535

// Explicitly declaring Float (less common)
let temperature: Float = 23.5

2.2.3 Truth Values: Bool

Bool is used for values that can only be true or false.

What it is: Represents a Boolean logical value. Why it’s important: Critical for decision-making in your code (e.g., “if this is true, do that”). How it functions: Can only hold one of two values: true or false.

// Inferring Bool
let isLoggedIn = true

// Explicitly declaring Bool
var gameIsOver: Bool = false

2.2.4 Text: String

String is used to store sequences of characters, like words, sentences, or names.

What it is: Represents a collection of characters, essentially text. Why it’s important: Used for all textual data in your applications, from user names to error messages. How it functions: You create string literals by enclosing text in double quotes (").

// Inferring String
let greeting = "Hello, Swift!"

// Explicitly declaring String
var userName: String = "CodeMaster"

// String concatenation (joining strings)
let fullName = firstName + " " + userName // This will try to combine Alice and CodeMaster, but firstName is a constant so it should be used.
                                        // Let's use it properly with a placeholder:
let message = "Welcome, \(firstName)!" // String interpolation - very common and powerful!
print(message) // Output: Welcome, Alice!

2.3 Type Safety and Type Conversion

Swift’s type safety is a powerful feature. It means you can’t accidentally treat a String as an Int or vice-versa. If you try to, Swift will give you a compile-time error, preventing potential bugs.

var myNumber: Int = 10
// myNumber = "Hello" // Error: Cannot assign value of type 'String' to type 'Int'

Sometimes, however, you do need to convert a value from one type to another. This is called type conversion (or type casting), and you must do it explicitly.

let stringNumber = "123"
// let actualNumber = stringNumber // Error: Cannot assign value of type 'String' to type 'Int'

// Explicitly convert String to Int
// Note: Int() returns an Optional Int, meaning the conversion might fail (e.g., if stringNumber was "hello")
// We'll dive deep into Optionals later, but for now, we'll use a force unwrap (!) for simplicity,
// assuming the conversion will always succeed in our examples. This is generally NOT safe in real code.
let actualNumber = Int(stringNumber)!
print("Converted number: \(actualNumber)") // Output: Converted number: 123

let myDouble = 3.14
let myInt = Int(myDouble) // Converts Double to Int, truncating the decimal part
print("Converted double to int: \(myInt)") // Output: Converted double to int: 3

let anotherInt = 5
let anotherString = String(anotherInt) // Converts Int to String
print("Converted int to string: \(anotherString)") // Output: Converted int to string: 5

Key Takeaway: Always be explicit when converting types. Swift won’t do it automatically for you to prevent unexpected behavior.

2.4 Step-by-Step Implementation: Playing in the Playground

Let’s put everything together in your Swift Playground. Follow these steps, adding each line and observing the results in the results sidebar.

  1. Open a new Playground: If you don’t have one open, go to Xcode -> File -> New -> Playground. Choose a Blank template.

  2. Declare a constant for your favorite programming language (hint: it’s Swift!):

    // Step 1: Declare a constant
    let favoriteLanguage = "Swift"
    print("My favorite language is: \(favoriteLanguage)")
    
  3. Declare a variable for your current learning progress (as a percentage):

    // Step 2: Declare a variable and update it
    var learningProgress: Double = 10.0 // Start at 10%
    print("Initial progress: \(learningProgress)%")
    
    learningProgress = 15.5 // You've learned more!
    print("Updated progress: \(learningProgress)%")
    
  4. Declare constants for a simple calculation:

    // Step 3: Use different basic types in a calculation
    let itemPrice: Double = 25.50
    let quantity: Int = 2
    let taxRate: Double = 0.08 // 8% tax
    
    // Calculate subtotal
    let subtotal = itemPrice * Double(quantity) // We need to convert quantity to Double for multiplication
    print("Subtotal: $\(subtotal)")
    
    // Calculate total with tax
    let totalCost = subtotal * (1 + taxRate)
    print("Total cost: $\(String(format: "%.2f", totalCost))") // Format to 2 decimal places
    

    Self-correction: Notice how we explicitly converted quantity from Int to Double using Double(quantity). This is Swift’s type safety in action! Also, String(format: "%.2f", totalCost) is a handy way to format Double values for display.

  5. Declare a boolean variable for a game state:

    // Step 4: Work with Booleans
    var gameIsActive: Bool = true
    print("Is game active? \(gameIsActive)")
    
    // Imagine something happens that ends the game
    gameIsActive = false
    print("Is game active after update? \(gameIsActive)")
    

2.5 Mini-Challenge: Your Personal Profile

It’s your turn to code!

Challenge: Create a small “personal profile” in your Playground.

  1. Declare a let constant for your name (a String).
  2. Declare a let constant for your birthYear (an Int).
  3. Declare a var variable for your currentCity (a String).
  4. Declare a var variable for your favoriteNumber (a Double, allowing for decimals if you wish).
  5. Declare a let constant hasPet (a Bool).
  6. Print out each of these values, clearly labeled, using string interpolation ("My name is \(name)").
  7. Update your currentCity to a different city and print it again.
  8. Update your favoriteNumber to a new value and print it again.

Hint: Remember to use let for values that won’t change and var for values that will. Pay attention to Swift’s type inference, but also try explicitly annotating types for practice (e.g., let name: String = "...").

What to observe/learn:

  • Confirm that let constants cannot be reassigned.
  • Confirm that var variables can be reassigned.
  • See how different data types behave and are printed.
  • Practice using string interpolation to combine text and variables/constants.

2.6 Common Pitfalls & Troubleshooting

Even with these basic building blocks, it’s easy to stumble. Here are a few common issues and how to resolve them:

  1. Trying to reassign a let constant:

    • Mistake: let myName = "John"; myName = "Jane"
    • Error Message: Cannot assign to value: 'myName' is a 'let' constant
    • Solution: If you intend for the value to change, declare it with var instead of let. If it’s truly a constant, accept that it can’t change.
  2. Type Mismatch (without explicit conversion):

    • Mistake: var count: Int = 5; count = "ten"
    • Error Message: Cannot assign value of type 'String' to type 'Int'
    • Solution: Swift is type-safe. You cannot assign a String to an Int variable. If you need to convert, use explicit type conversion (e.g., Int("10")!). Ensure the data types match the kind of information you’re storing.
  3. Forgetting initial value:

    • Mistake: var myVariable: Int (without assigning a value)
    • Error Message: Variable 'myVariable' used before being initialized (if you try to use it) or Type annotation missing in pattern (if not used immediately).
    • Solution: All variables and constants in Swift must have an initial value before they are used. Always initialize them: var myVariable: Int = 0 or var myVariable = 0.

2.7 Summary

Phew! You’ve just taken your first significant steps into the world of Swift programming. Here’s a quick recap of what we covered:

  • let constants: For values that do not change after being set. Prefer let for safety and clarity.
  • var variables: For values that can change after being set.
  • Basic Data Types:
    • Int: Whole numbers (e.g., 10, -5).
    • Double: Decimal numbers with high precision (e.g., 3.14, 19.99). This is the default for floating-point literals.
    • Float: Decimal numbers with less precision (less commonly used).
    • Bool: True or false values (e.g., true, false).
    • String: Text (e.g., "Hello World").
  • Type Inference: Swift’s ability to automatically determine a variable’s type based on its initial value.
  • Type Safety: Swift prevents you from mixing types without explicit conversion, catching errors early.
  • Type Conversion: Explicitly converting values from one type to another (e.g., Int(someDouble), String(someInt)).
  • String Interpolation: A powerful way to embed variables and constants directly into strings using \(...).

You’re now equipped with the foundational knowledge to store and manipulate basic data in Swift. This is incredibly important, as almost everything you do in programming revolves around working with data.

In the next chapter, we’ll build on this by exploring how to make your programs smart and responsive using operators and control flow, allowing your code to make decisions and repeat actions!

References

This page is AI-assisted and reviewed. It references official documentation and recognized resources where relevant.