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
237: Swift Build (Experimental Build System)
Why bother with the CLI build system over just hitting "Run" in Xcode?
I get it—Xcode's "Play" button is addictive. It handles the build, the launch, and the debugger in one click. But when you're working on larger systems or setting up a CI/CD pipeline, you can't rely on a GUI. The experimental build system provided by the Swift toolchain (which powers swift build) is designed to be deterministic and portable. It strips away the "magic" of .xcodeproj files, which are notoriously difficult to merge in Git.
When I'm debugging a weird build failure that only happens on the build server and not on my MacBook, the first thing I do is drop into the terminal. By using the command line, you see the raw compiler invocations. You get a clear view of exactly which flags are being passed to swiftc, which is often hidden behind several layers of abstraction in Xcode's Build Settings.
How do I pass specific compiler flags without an Xcode project file?
This is where things get a bit tricky because you can't just click a checkbox in a "Build Settings" tab. If you need to pass a flag directly to the Swift compiler—say, you're using an experimental feature or need to disable certain warnings for a legacy module—you use the -Xswiftc flag. This tells the build system, "Take the next argument and hand it directly to the compiler."
For example, if I'm working on a high-performance math library and I want to enable whole-module optimization to squeeze out more speed, I'd run it like this:
swift build -c release -Xswiftc -whole-module-optimization
If you're dealing with a mixed-language project and need to pass something to the C compiler, you'll use -Xcc. I've found that being explicit with these flags in a shell script is way more reliable than hoping your teammates have the same "User-Defined Settings" configured in their local Xcode environment.
Where does the build system actually put the binaries?
If you're used to the Xcode DerivedData folder, the Swift build system's layout will feel a bit sparse. By default, it creates a hidden .build directory in your project root. Inside there, you'll find a debug or release folder depending on the configuration you chose.
I often see developers get confused when they can't find their executable. If you've built a target called MyNetworkTool, the binary isn't just floating in the root; it's buried in .build/debug/MyNetworkTool. To avoid hunting through folders, you can use the --show-bin-path flag:
swift build --show-bin-path
I usually pipe this into a variable in my automation scripts so I can run tests or benchmarks immediately after the build completes without hardcoding a path that might change based on the OS.
📋 Practical Task
Exercise: Manually Optimizing a Matrix Math Module
In this exercise, you will move away from the IDE to build a performance-critical module using the Swift CLI build system.
- Create a new directory named
MathOptimizerand initialize it as a Swift package:swift package init --type executable. - In
main.swift, implement a simple loop that performs 10 million additions to simulate a heavy workload. - Run a standard debug build using
swift buildand time how long the resulting binary takes to execute. - Now, rebuild the project using the
-c releaseconfiguration and pass the-O(optimize for speed) flag explicitly using-Xswiftc -O. - Locate the release binary using
swift build --show-bin-pathand compare the execution time against the debug version. - Document the time difference; you should see a significant performance boost in the release build.
There are no comments for now.