Swift Switch Case
Introduction
The switch
statement is a powerful control flow mechanism in Swift that allows you to compare a value against multiple possible matching patterns. It's an alternative to if-else statements that is particularly useful when you need to check a value against many possible conditions. Unlike switch statements in other languages, Swift's version is much more versatile and type-safe, with features like pattern matching, value binding, and the absence of implicit fallthrough.
Basic Syntax
The basic syntax of a Swift switch statement looks like this:
switch valueToCheck {
case pattern1:
// code to execute if value matches pattern1
case pattern2, pattern3:
// code to execute if value matches pattern2 or pattern3
default:
// code to execute if no patterns match
}
Let's see this in action with a simple example:
let someCharacter: Character = "z"
switch someCharacter {
case "a":
print("The first letter of the alphabet")
case "z":
print("The last letter of the alphabet")
default:
print("Some other character")
}
// Output: The last letter of the alphabet
Key Features of Swift Switch Statements
1. Exhaustiveness
Swift requires that your switch
statements are exhaustive, meaning they must cover all possible values of the type being checked, or include a default
case:
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a", "A":
print("The letter A")
case "b", "B":
print("The letter B")
case "c", "C":
print("The letter C")
default:
print("Some other character")
}
// Output: The letter A
2. No Implicit Fallthrough
Unlike C and other languages, Swift doesn't fall through to the next case by default. Once a case is matched and executed, the switch statement completes without checking any other cases:
let number = 5
switch number {
case 5:
print("The number is 5")
// No need for break statement
case 6:
print("The number is 6")
default:
print("The number is neither 5 nor 6")
}
// Output: The number is 5
3. Range Matching
Swift allows matching ranges of values in switch cases:
let approximateCount = 62
switch approximateCount {
case 0:
print("No items")
case 1..<5:
print("A few items")
case 5..<12:
print("Several items")
case 12..<100:
print("Dozens of items")
case 100..<1000:
print("Hundreds of items")
default:
print("Many items")
}
// Output: Dozens of items
4. Tuple Pattern Matching
Switch cases can match against tuples to test multiple values:
let point = (2, 0)
switch point {
case (0, 0):
print("Origin")
case (_, 0):
print("On the x-axis")
case (0, _):
print("On the y-axis")
case (-2...2, -2...2):
print("Inside the box")
default:
print("Outside the box")
}
// Output: On the x-axis
5. Value Binding
You can bind part of the matched value to a constant or variable for use within the case's body:
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
print("On the x-axis with an x value of \(x)")
case (0, let y):
print("On the y-axis with a y value of \(y)")
case let (x, y):
print("Somewhere else at (\(x), \(y))")
}
// Output: On the x-axis with an x value of 2
6. Where Clauses
You can use where
clauses to check for additional conditions:
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
print("On the line x = y")
case let (x, y) where x == -y:
print("On the line x = -y")
case let (x, y):
print("At the point (\(x), \(y))")
}
// Output: On the line x = -y
7. Compound Cases
Multiple patterns can be combined into a single case, separated by commas:
let someCharacter2: Character = "e"
switch someCharacter2 {
case "a", "e", "i", "o", "u":
print("\(someCharacter2) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
"n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
print("\(someCharacter2) is a consonant")
default:
print("\(someCharacter2) is not a vowel or consonant")
}
// Output: e is a vowel
Practical Examples
Example 1: Game State Management
enum GameState {
case start
case playing
case paused
case gameOver
}
func handleGameState(_ state: GameState) {
switch state {
case .start:
print("Game is starting. Loading resources...")
// Initialize game resources
case .playing:
print("Game is in progress. Update game elements.")
// Update game elements
case .paused:
print("Game is paused. Show pause menu.")
// Display pause menu
case .gameOver:
print("Game over. Show final score and options.")
// Show game over screen
}
}
let currentState = GameState.paused
handleGameState(currentState)
// Output: Game is paused. Show pause menu.
Example 2: HTTP Response Handler
enum HTTPResponse {
case success(Int, String)
case error(Int, String)
case redirect(Int, String)
}
func handleResponse(_ response: HTTPResponse) {
switch response {
case .success(let code, let message):
print("Success with code \(code): \(message)")
// Process successful response
case .error(let code, _) where code >= 500:
print("Server error \(code)")
// Handle server error
case .error(let code, let message):
print("Client error \(code): \(message)")
// Handle client error
case .redirect(let code, let location):
print("Redirect \(code) to \(location)")
// Follow redirect
}
}
let successResponse = HTTPResponse.success(200, "OK")
handleResponse(successResponse)
// Output: Success with code 200: OK
let serverError = HTTPResponse.error(500, "Internal Server Error")
handleResponse(serverError)
// Output: Server error 500
Example 3: Calculator Application
enum Operation {
case addition
case subtraction
case multiplication
case division
}
func calculate(_ a: Double, _ b: Double, operation: Operation) -> Double? {
switch operation {
case .addition:
return a + b
case .subtraction:
return a - b
case .multiplication:
return a * b
case .division:
if b == 0 {
return nil // Cannot divide by zero
}
return a / b
}
}
if let result = calculate(10, 5, operation: .division) {
print("Result: \(result)")
} else {
print("Invalid operation")
}
// Output: Result: 2.0
Common Pitfalls and Best Practices
1. Always Ensure Exhaustiveness
Swift requires your switch statements to be exhaustive. Either include all possible cases or use a default case:
enum Compass {
case north, south, east, west
}
let direction = Compass.west
switch direction {
case .north:
print("Heading north")
case .south:
print("Heading south")
case .east:
print("Heading east")
case .west:
print("Heading west")
}
// This works because all cases are covered
// If we add a new case to Compass but don't update this switch,
// the compiler will generate an error
2. Avoid Empty Cases
If a case doesn't need to execute any code, you should explicitly declare it:
switch someValue {
case valueA:
doSomething()
case valueB:
break // Explicitly do nothing
default:
doSomethingElse()
}
3. Use Fallthrough Intentionally
If you need fallthrough behavior, Swift provides the fallthrough
keyword:
let integerToDescribe = 5
switch integerToDescribe {
case 5:
print("The number is 5")
fallthrough
case 6:
print("The number is 5 or 6") // This will also execute when the case is 5
default:
print("The number is neither 5 nor 6")
}
// Output:
// The number is 5
// The number is 5 or 6
Summary
The Swift switch
statement is a powerful control flow mechanism that offers:
- Exhaustiveness checking for safety
- No implicit fallthrough between cases
- Pattern matching with ranges, tuples, and value binding
- Additional condition checking with
where
clauses - Multiple patterns in a single case
Its versatility makes it preferable to lengthy if-else chains in many scenarios, particularly when dealing with multiple conditions or pattern matching.
Exercises
-
Create a switch statement that categorizes temperatures as "freezing" (below 32°F), "cold" (32-50°F), "mild" (51-70°F), "warm" (71-90°F), or "hot" (above 90°F).
-
Write a function that takes a tuple containing coordinates (x, y) and uses a switch statement to determine which quadrant the point falls in (or if it's on an axis).
-
Create an enum representing different types of vehicles (car, truck, motorcycle, bicycle) and write a switch statement that returns the number of wheels for each type.
-
Write a function that uses a switch statement with value binding to extract and process information from different kinds of optionals.
Additional Resources
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)