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
216: Building a Split-View Master-Detail App for iPad
A few years ago, I was reviewing a PR for a colleague who had just finished a polished note-taking app. It worked beautifully on the iPhone, but when he ran it on an iPad Pro, it looked... well, lonely. He had just let the views scale up, leaving massive gutters of white space and a single column of text that stretched across the entire 12.9-inch screen. It felt like looking at a giant postcard. He asked me, "Why does it feel so empty?" The answer was simple: he wasn't utilizing the screen real estate. On a tablet, users expect a "Master-Detail" flow—the ability to see their list and their content side-by-side without constant back-and-forth navigation.
Designing the Three-Column Architecture
In modern SwiftUI, the NavigationSplitView is your primary tool for solving this "empty space" problem. It allows you to define a hierarchy—usually a sidebar, a content list, and a detail view—that the system automatically manages based on the device's screen size. For our example, let's imagine we're building a Recipe Book. On an iPad, you want your categories (Breakfast, Dinner, Dessert) in the sidebar, the list of recipes for that category in the middle, and the actual cooking instructions in the detail pane.
struct RecipeAppView: View {
@State private var selectedCategory: RecipeCategory?
@State private var selectedRecipe: Recipe?
var body: some View {
NavigationSplitView {
List(categories, selection: $selectedCategory) { category in
Text(category.name).tag(category)
}
.navigationTitle("Categories")
} content: {
if let category = selectedCategory {
List(category.recipes, selection: $selectedRecipe) { recipe in
Text(recipe.title).tag(recipe)
}
.navigationTitle(category.name)
} else {
Text("Select a category")
}
} detail: {
if let recipe = selectedRecipe {
RecipeDetailView(recipe: recipe)
} else {
Text("Select a recipe to get started")
}
}
}
}
Binding Selection for Seamless Transitions
The magic here lies in the selection bindings. Notice how I used $selectedCategory and $selectedRecipe. By tagging each item in the list with the object itself, SwiftUI knows exactly which item is active. When the user taps a category in the sidebar, the content column updates instantly. When they tap a recipe, the detail view swaps in.
I've found that the biggest mistake developers make is forgetting to handle the "empty state." If you don't provide a fallback view in the detail closure (like the "Select a recipe" text above), the user is greeted with a blank screen upon launch. It feels broken, even if it's technically working. Always give your user a hint about what they're supposed to do next.
Adapting to the Compact Column Style
One of the best things about NavigationSplitView is that you don't have to write separate code for iPhone and iPad. On an iPhone, SwiftUI automatically collapses this three-column layout into a single-column stack. The sidebar becomes the first screen, the content list becomes the second, and the detail view the third.
However, you can control this behavior using NavigationSplitViewVisibility. If you want the sidebar to be hidden by default on iPad to give more room to the content, you can pass a visibility state to the initializer. I usually recommend leaving it to the system default unless your app is content-heavy (like a photo editor), where the sidebar is secondary to the main workspace.
📋 Practical Task
The Gourmet Recipe Browser Layout
Your task is to build a functional three-column split view for a gourmet recipe application. You will need to implement the following:
- Data Model: Create a
RecipeCategorystruct (with a name and an array of recipes) and aRecipestruct (with a title and a description). Both must conform toHashableandIdentifiable. - Sidebar: A list of at least three categories.
- Content Column: A list that displays the recipes belonging to the currently selected category.
- Detail Column: A view that displays the full description of the selected recipe.
- Empty States: Ensure that both the content and detail columns show a descriptive
Textview (e.g., "Please select a category") when no item is selected.
Test your implementation by running it in the iPad Pro simulator to verify the three-column layout, and then in the iPhone 15 simulator to ensure it collapses into a standard navigation stack.
There are no comments for now.