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
90: Declarative UI Concepts in SwiftUI
Imagine you're ordering a custom pizza. If you were using an imperative approach, you'd have to walk into the kitchen and give the chef a step-by-step manual: "First, roll out 12 inches of dough. Now, spread two tablespoons of tomato sauce in a circular motion. Next, sprinkle 100g of mozzarella. Finally, place twelve pepperonis evenly across the top." If you suddenly decided you wanted mushrooms instead of pepperoni, you'd have to tell the chef to pick off the pepperoni and then add the mushrooms. It's tedious, and there are a lot of places to mess up the sequence.
A declarative approach is much simpler. You just hand the chef a ticket that says: "Large Pepperoni Pizza." You've described the end state you want. You don't care how the chef rolls the dough or which spoon they use for the sauce; you just care that the result matches your description. If you want mushrooms, you just change the ticket to "Large Mushroom Pizza," and the chef handles the transition to make that a reality.
The Shift from "How" to "What"
For years, iOS development was imperative (think UIKit). We spent our time writing code to manually update the UI: label.text = "Loading...", activityIndicator.startAnimating(), or view.isHidden = true. We were the ones managing the transition from one state to another. If you forgot to hide a view when a network request failed, the user ended up with a broken UI. I've spent countless hours debugging those exact kinds of "state mismatch" bugs.
SwiftUI flips this. Instead of writing a series of commands to change the UI, you write a function that describes what the UI should look like for any given state. The framework then takes a look at your state and "diffs" it—calculating exactly what changed and updating only the parts of the screen that need it.
Connecting State to the Screen
Let's look at a real scenario. Suppose we're building a "Follow" button for a social media profile. In the old way, you'd have to manually change the button's title and color whenever the user tapped it. In SwiftUI, we just describe the button's appearance based on a boolean value.
struct ProfileFollowButton: View {
// This is our "ticket" or source of truth
@State private var isFollowing = false
var body: some View {
Button(action: {
// We don't tell the button to change color here.
// We just change the data.
isFollowing.toggle()
}) {
Text(isFollowing ? "Following" : "Follow")
.padding()
.background(isFollowing ? Color.gray : Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
}
}
}
Notice that inside the Button action, I'm not calling a function like updateButtonUI(). I'm simply toggling a piece of data. Because the body property is a computed property, SwiftUI says, "Oh, isFollowing changed! I need to re-run that description and update the screen."
Letting SwiftUI Do the Heavy Lifting
The magic here is that the UI is a function of the state. Mathematically, it looks like UI = f(state). This removes an entire category of bugs. You no longer have to worry about the button saying "Following" while the database still thinks the user is "Unfollowed" because you forgot to call the update method in one specific edge case.
When you're writing SwiftUI, I want you to stop thinking about "changing the screen" and start thinking about "updating the data." If a view isn't looking the way you expect, don't look for the line of code that changes the color—look for the state variable that controls that color. If the state is correct, the UI will follow.
📋 Practical Task
Build a Task Completion Toggle
Your goal is to create a view for a single To-Do item that demonstrates declarative UI principles. Instead of manually changing the text style, the UI should automatically reflect the "completed" status of the task.
Requirements:
- Create a
TodoItemViewthat contains a@Stateboolean calledisCompleted. - Include a
Textview displaying a task name (e.g., "Buy groceries"). - Include a
Buttonthat toggles theisCompletedstate. - Declarative Logic:
- When
isCompletedistrue, the text should have a.strikethrough()modifier and the color should be.gray. - When
isCompletedisfalse, the text should be.black(or.primary) with no strikethrough. - The button text should switch between "Done" and "Undo".
- When
There are no comments for now.