Swift
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Optionals
-
Section 4: Object-Oriented and Value Types
-
Section 5: Memory Management
-
Section 6: Generics and Error Handling
-
Section 7: Concurrency
-
Section 8: Working with Collections
-
Section 9: Codable and Data Handling
-
Section 10: Protocol-Oriented Programming
-
Section 11: Testing and Tooling
-
Section 12: Practical Projects
-
Section 13: Interview Practice
-
Section 14: More Practice Exercises
-
Section 15: More Standard Library
-
Section 16: Advanced Concurrency
-
Section 17: Foundation Framework Deep Dive
-
Section 18: URLSession and Networking Deep Dive
-
Section 19: Combine Framework
-
Section 20: SwiftUI Fundamentals for Swift Developers
-
Section 21: Server-Side Swift with Vapor
-
Section 22: Swift Package Manager Deep Dive
-
Section 23: Swift Concurrency Deep Dive
-
Section 24: More Language Features
-
Section 25: Error Handling Deep Dive
-
Section 26: Testing Deep Dive
-
Section 27: Data Structures and Algorithms in Swift
-
Section 28: More Practice Exercises
-
Section 29: More Interview Practice
-
Section 30: Swift Macros (Swift 5.9+)
-
Section 31: Property Wrappers Ecosystem
-
Section 32: Swift Interop Deep Dive
-
Section 33: iOS App Architecture Patterns
-
Section 34: Performance and Debugging
-
Section 35: App Distribution and CI/CD
-
Section 36: More Practical Projects
-
Section 37: SwiftData and Persistence
-
Section 38: More Design Patterns
-
Section 39: More Review and Practice
-
Section 40: More Foundation Deep Dive
-
Section 41: Advanced Collections in Swift
-
Section 42: Advanced Generics Practice
-
Section 43: UIKit for Legacy and Hybrid Apps
-
Section 44: watchOS and visionOS Development Basics
-
Section 45: More Networking Patterns
-
Section 46: More Testing Practice
-
Section 47: Accessibility in Swift Apps
-
Section 48: Localization
-
Section 49: More Practical Projects Round 2
-
Section 50: Swift Charts Framework
-
Section 51: More Interview and Algorithm Practice
-
Section 52: Final Practice and Mastery
-
Section 53: Swift Compiler and Build System
-
Section 54: More Concurrency Practice
-
Section 55: App Store Guidelines and Review
-
Section 56: More Design and Architecture
35: Arrays, Sets, and Dictionaries
I want to show you a snippet of code I reviewed recently. A junior dev was building a simple "Guest List" manager for an event app. They were using an Array to keep track of email addresses and a Dictionary to store meal preferences. It looked fine at first glance, but it had two major flaws that would have caused a production crash and a lot of data duplication.
var guestEmails = ["alice@example.com", "bob@example.com", "alice@example.com"]
var mealPreferences = ["alice@example.com": "Vegan", "bob@example.com": "Gluten-Free"]
// Trying to get a preference for someone not on the list
let guestEmail = "charlie@example.com"
let preference = mealPreferences[guestEmail]!
print("Guest preference: \(preference)")
If you run this, it crashes instantly. Why? Because mealPreferences[guestEmail] returns an optional. Since Charlie isn't in the dictionary, it returns nil, and the force-unwrap operator (!) tells Swift, "I swear this isn't nil," which is a lie. Beyond the crash, notice the guestEmails array. Alice is in there twice. In a real app, that means she gets two confirmation emails and takes up two seats.
Switching to Sets for Unique Collections
The first thing we need to fix is the duplicate email problem. When I care about uniqueness and don't particularly care about the order of the items, I stop using Arrays and reach for a Set. A Set is essentially an unordered collection of unique elements. If you try to insert "alice@example.com" twice, the Set just ignores the second attempt.
// Change this from [String] to Set<String>
var guestEmails: Set = ["alice@example.com", "bob@example.com", "alice@example.com"]
print(guestEmails.count) // Output: 2
The trade-off here is that you lose index-based access. You can't ask a Set for "the element at index 0" because there is no guaranteed order. But the win is massive: checking if a Set contains a specific item is incredibly fast, regardless of whether you have ten guests or ten million.
Handling Dictionary Optionals Safely
Now, let's kill that crash. In Swift, accessing a value in a dictionary always returns an optional because the compiler has no way of knowing if the key you're asking for actually exists. I've seen too many developers use ! because they "know" the key is there, but user input is unpredictable. Never trust your keys.
The cleanest way to handle this is using nil-coalescing (??) to provide a sensible default, or optional binding (if let) if you need to run specific logic only when a value exists.
let guestEmail = "charlie@example.com"
// Option A: Provide a default value
let preference = mealPreferences[guestEmail] ?? "No preference specified"
print("Guest preference: \(preference)")
// Option B: Only execute if the guest exists
if let specificPreference = mealPreferences[guestEmail] {
print("Preparing a \(specificPreference) meal.")
} else {
print("This guest isn't on the list!")
}
Choosing the Right Tool for the Job
I usually tell my mentees to think about their data requirements before typing a single bracket. If you're debating between these three, ask yourself these questions:
- Do I need to maintain a specific order? Use an Array. It's the workhorse for lists, queues, and stacks.
- Do I need to ensure every item is unique? Use a Set. It's perfect for things like IDs, tags, or a list of "liked" posts.
- Do I need to associate a value with a unique key? Use a Dictionary. This is your go-to for caches, configuration settings, or any "lookup table" scenario.
One last tip: remember that for a type to be used as a key in a Dictionary or an element in a Set, it must conform to the Hashable protocol. Standard types like String, Int, and Double already do this, but if you create your own struct to use as a key, you'll need to add that conformance.
📋 Practical Task
Build a Digital Library Inventory
You are building a system to track a small library's inventory. You need to manage a list of unique Book ISBNs and map those ISBNs to the actual titles of the books.
Requirements:
- Create a
Setof strings calledcatalogedISBNs. Add three different ISBNs to it, including one duplicate (which should be ignored). - Create a
DictionarycalledbookTitleswhere the Key is the ISBN (String) and the Value is the Title (String). - Write a function
findBook(isbn: String)that:- Checks if the ISBN exists in the
catalogedISBNsset. - If it exists, retrieves the title from the
bookTitlesdictionary using safe optional unwrapping. - If it doesn't exist or the title is missing, returns a message saying "Book not found in inventory."
- Checks if the ISBN exists in the
- Test your function with one ISBN that exists and one that does not.
There are no comments for now.