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
94: List and ForEach in SwiftUI
I've been thinking about how to organize my current side project tasks, so instead of using a Trello board, I figured I'd just build a quick backlog viewer in SwiftUI. It seems simple enough, but this is where we usually run into the difference between "just showing some data" and "building a proper list."
The "Manual" Way
If I just have a few tasks, I could probably just stack them. Let's see what happens if I use a VStack and some hardcoded strings.
struct BacklogView: View {
var body: some View {
VStack {
Text("Fix memory leak in Parser")
Text("Update README")
Text("Add unit tests for Auth")
}
}
}
It works, but it's hideous. Everything is bunched up in the center of the screen, there are no dividers, and if I add twenty more tasks, they'll just bleed off the top and bottom of the screen because a VStack doesn't scroll by default. This is clearly not how we want to handle a dynamic set of data.
Letting ForEach do the heavy lifting
I don't want to hardcode every single task. I'll put them in an array and use ForEach. Now, here is a common point of confusion: ForEach in SwiftUI isn't exactly a "for loop" like you'd find in a standard Swift function. It's actually a view that generates other views.
let tasks = ["Fix memory leak", "Update README", "Add unit tests"]
var body: some View {
VStack {
ForEach(tasks, id: \.self) { task in
Text(task)
}
}
}
That id: \.self part? That's the "magic" that usually trips people up. SwiftUI needs to know which item is which so that if one task changes or gets deleted, it doesn't have to redraw the entire screen. By saying \.self, I'm telling SwiftUI, "The string itself is the unique identifier." This works for simple strings, but it's a nightmare if you have two tasks named "Fix bug"—SwiftUI will get confused about which one you're interacting with.
Switching to a proper List
The VStack with ForEach still doesn't feel like a real iOS app. It's just a pile of text. Let's swap that VStack for a List.
var body: some View {
List {
ForEach(tasks, id: \.self) { task in
Text(task)
}
}
}
Immediately, everything looks professional. We've got the standard system spacing, the separators between rows, and—most importantly—it scrolls automatically. Interestingly, you can actually put the array directly into the List without an explicit ForEach, but I prefer keeping the ForEach inside because it gives us more control if we want to mix in other types of views (like a header or a section) later on.
Solving the Identity Crisis
Now, a real app wouldn't just use strings. My tasks need IDs, priority levels, and completion statuses. Let's try to use a struct.
struct ProjectTask {
var name: String
var priority: Int
}
let myTasks = [
ProjectTask(name: "Fix memory leak", priority: 1),
ProjectTask(name: "Update README", priority: 3)
]
If I try to throw myTasks into a ForEach now, the compiler starts screaming at me. It's demanding that the data be Identifiable. Instead of typing id: \.name every single time (which is risky because names can overlap), the professional move is to make the struct conform to the Identifiable protocol.
struct ProjectTask: Identifiable {
let id = UUID() // This generates a unique ID automatically
var name: String
var priority: Int
}
// Now the ForEach becomes much cleaner:
ForEach(myTasks) { task in
Text(task.name)
}
By adding Identifiable, I've removed the need to specify the id parameter in the ForEach. SwiftUI just looks for the id property on the object. It's cleaner, safer, and it's how almost every professional SwiftUI project handles lists of data.
📋 Practical Task
Build a "Favorite Coffee Shop" Directory
Create a view that displays a list of coffee shops. You will need to:
- Define a
CoffeeShopstruct that conforms toIdentifiable. It should have aname(String) and asignatureDrink(String). - Create an array of at least four
CoffeeShopinstances. - Use a
ListandForEachto display these shops. - Inside the
ForEach, use aVStack(with alignment.leading) for each row so that the shop name is prominent and the signature drink is displayed underneath it in a smaller, secondary font color.
There are no comments for now.