We've already seen how arrays let us store lots of values in one place. But arrays have a problem — you have to remember positions to get your data back.
What if there was a smarter way? 🤔
That's where dictionaries come in.
The Problem with Arrays
Let's say you're storing a character's profile from My Hero Academia:
var hero = ["Izuku Midoriya", "One For All", "Class 1-A"]
Now to read that data back:
print("Name: \(hero[0])")
print("Quirk: \(hero[1])")
print("Class: \(hero[2])")
This works... but it's fragile. What if someone removes an item from the array?
print("Name: \(hero[0])")
hero.remove(at: 1)
print("Quirk: \(hero[1])") // ❌ Now prints "Class 1-A" — wrong!
print("Class: \(hero[2])") // 💥 CRASH — index doesn't exist anymore
Everything falls apart. You can't trust positions. You have to remember what index holds what — and that's a recipe for bugs 🐛
Enter Dictionaries
Instead of positions, dictionaries use keys — labels you choose yourself to describe exactly what each value means.
Here's the same hero profile, rewritten as a dictionary:
let hero = [
"name": "Izuku Midoriya",
"quirk": "One For All",
"class": "Class 1-A"
]
Now reading data is crystal clear:
print(hero["name", default: "Unknown"])
print(hero["quirk", default: "Unknown"])
print(hero["class", default: "Unknown"])
No guessing. No positions. No crashes from removed items. Just clean, readable code 🌸
🔑 Keys and Values
Every item in a dictionary has two parts:
| Part | What it is | Example |
|---|---|---|
| Key | The label you use to find the data | "name" |
| Value | The actual data stored | "Izuku Midoriya" |
Think of it like a character profile card — you look up the field name (key) and get the info (value) back instantly, even if there are thousands of entries. Swift optimizes dictionaries specifically for this kind of fast lookup ⚡
⚠️ Why Dictionaries Return Optionals
Try reading a key that doesn't exist in the dictionary:
print(hero["villain"])
Swift won't crash — but it will return nil, meaning nothing. That's because Swift can't guarantee that every key you ask for actually exists. This is why reading from a dictionary gives you back an optional value — it might be there, or it might not.
You'll see a warning like:
Expression implicitly coerced from 'String?' to 'Any'
Swift is telling you "hey, are you sure this value exists?" 🤔
We'll cover optionals in depth later in this series — but for now, there's a simple and clean solution.
🛡️ Default Values — Your Safety Net
When reading from a dictionary, you can provide a default value that gets used if the key doesn't exist:
print(hero["name", default: "Unknown"]) // Izuku Midoriya
print(hero["villain", default: "Unknown"]) // Unknown
No crash. No warning. Just a safe fallback value. ✅
Here's a more real-world example — tracking exam scores:
let examScores = [
"math": 95,
"english": 88,
"history": 72
]
print(examScores["math", default: 0]) // 95
print(examScores["science", default: 0]) // 0 — didn't take it
💡 When should you use a default value?
- Use
default: 0if a missing score means the student didn't take the exam- Skip the default and handle
nildirectly if missing means they haven't taken it yetThe right choice depends on what your app needs to do with that missing data.
Different Types for Keys and Values
Dictionaries aren't limited to String keys and String values. You can mix and match types.
String keys, Bool values — tracking which characters have awakened their powers:
let awakenedPowers = [
"Izuku": true,
"Bakugo": true,
"Mineta": false
]
Integer keys, String values — tracking anime seasons by year:
let seasonYears = [
2013: "Attack on Titan S1",
2017: "Attack on Titan S2",
2022: "Attack on Titan Final Season"
]
print(seasonYears[2013, default: "Unknown"])
// Attack on Titan S1
Creating Empty Dictionaries
Just like arrays, you can start with an empty dictionary and fill it in over time.
var characterStats = [String: Int]()
characterStats["strength"] = 95
characterStats["speed"] = 88
characterStats["intelligence"] = 70
The [String: Int] syntax means:
-
Keys will be
String -
Values will be
Int
You can do the same for any type combination — [String: String], [Int: Bool], and so on.
🔄 Updating Values — No Duplicates Allowed
Dictionaries do not allow duplicate keys. If you assign a value to a key that already exists, Swift simply overwrites the old value:
var rivalry = [String: String]()
rivalry["Naruto"] = "Sasuke"
print(rivalry["Naruto", default: "Unknown"]) // Sasuke
rivalry["Naruto"] = "Pain"
print(rivalry["Naruto", default: "Unknown"]) // Pain
The old value is gone — replaced by the new one. So every key in a dictionary is always unique. 🔒
🛠️ Useful Dictionary Operations
📏 Count — How many entries?
let heroTeam = ["leader": "Levi", "scout": "Eren", "medic": "Hange"]
print(heroTeam.count) // 3
🗑️ Remove Everything
var tempData = ["key1": "value1", "key2": "value2"]
tempData.removeAll()
print(tempData.count) // 0
🧩 Putting It All Together
Here's a mini character profile system using everything we covered:
// Create a character profile
var profile = [String: String]()
profile["name"] = "Levi Ackerman"
profile["rank"] = "Captain"
profile["squad"] = "Survey Corps"
profile["weapon"] = "Omni-Directional Mobility Gear"
// Read profile safely
print(profile["name", default: "Unknown"]) // Levi Ackerman
print(profile["rank", default: "Unknown"]) // Captain
print(profile["hometown", default: "Unknown"]) // Unknown
// Update a value
profile["rank"] = "Humanity's Strongest"
print(profile["rank", default: "Unknown"]) // Humanity's Strongest
// Check size
print(profile.count) // 4
// Clear everything
profile.removeAll()
print(profile.count) // 0
🆚 Arrays vs Dictionaries — Which to Use?
| Arrays | Dictionaries | |
|---|---|---|
| Access by | Position (index) | Label (key) |
| Order | ✅ Preserved | ❌ Not guaranteed |
| Duplicate items | ✅ Allowed | ❌ Keys must be unique |
| Safe access | ❌ Wrong index = crash | ✅ Missing key = nil |
| Best for | Ordered lists | Labelled data / lookups |
🌟 Wrap Up
Dictionaries solve a real problem that arrays can't — they let you store and retrieve data using meaningful labels instead of fragile position numbers.
- Use arrays when order matters and items are accessed by position
- Use dictionaries when you want to look things up by name
In real apps you'll reach for dictionaries constantly — user profiles, settings, API responses, game stats, and so much more. Getting comfortable with them now will pay off big time down the road 💪
Next up, we'll look at sets — another way to store data, but with some very interesting superpowers. See you there! 👋
Top comments (0)