Swift Guard Statement

Early exit and safe unwrapping with guard statements

🛡️ What is Guard Statement?

Swift guard statements provide early exit from functions when conditions aren't met. They improve code readability by handling failure cases upfront and safely unwrapping optionals with cleaner syntax.


// Basic guard example
func processAge(_ age: Int?) {
    guard let validAge = age, validAge >= 0 else {
        print("Invalid age!")
        return
    }
    print("Age is \(validAge)")
}
                                    

Output:

processAge(25) → Age is 25

processAge(nil) → Invalid age!

Guard Statement Benefits

🚪

Early Exit

Exit function when conditions fail

guard condition else {
    return // Must exit
}
📦

Safe Unwrapping

Unwrap optionals safely

guard let value = optional else {
    return
}
📖

Readable Code

Reduces nested if statements

// Happy path at main level
guard isValid else { return }
// Continue with main logic
🔒

Scope Extension

Unwrapped values available after guard

guard let name = name else { return }
print(name) // Available here

🔹 Guard vs If-Let Comparison

See how guard improves code structure:

// Using if-let (nested structure)
func processUserIfLet(_ name: String?, _ age: Int?) {
    if let userName = name {
        if let userAge = age {
            if userAge >= 18 {
                print("Welcome \(userName), age \(userAge)")
            } else {
                print("Sorry, must be 18 or older")
            }
        } else {
            print("Age is required")
        }
    } else {
        print("Name is required")
    }
}

// Using guard (flat structure)
func processUserGuard(_ name: String?, _ age: Int?) {
    guard let userName = name else {
        print("Name is required")
        return
    }
    
    guard let userAge = age else {
        print("Age is required")
        return
    }
    
    guard userAge >= 18 else {
        print("Sorry, must be 18 or older")
        return
    }
    
    print("Welcome \(userName), age \(userAge)")
}

Output:

Both functions produce the same results, but guard version is more readable

🔹 Multiple Conditions in Guard

Combine multiple conditions in a single guard statement:

func createUser(name: String?, email: String?, age: Int?) {
    guard let userName = name, !userName.isEmpty,
          let userEmail = email, userEmail.contains("@"),
          let userAge = age, userAge >= 13 else {
        print("Invalid user data provided")
        return
    }
    
    print("Creating user: \(userName), \(userEmail), age \(userAge)")
}

// Test the function
createUser(name: "Alice", email: "[email protected]", age: 25)
createUser(name: "", email: "invalid-email", age: 12)
createUser(name: "Bob", email: "[email protected]", age: 30)

Output:

Creating user: Alice, [email protected], age 25

Invalid user data provided

Creating user: Bob, [email protected], age 30

🔹 Guard in Loops

Use guard with continue in loops:

let numbers = ["1", "2", "abc", "4", "xyz", "6"]

for numberString in numbers {
    guard let number = Int(numberString) else {
        print("Skipping invalid number: \(numberString)")
        continue
    }
    
    guard number % 2 == 0 else {
        print("Skipping odd number: \(number)")
        continue
    }
    
    print("Processing even number: \(number)")
}

// Array processing example
let users = [
    ["name": "Alice", "age": "25"],
    ["name": "Bob"],
    ["age": "30"],
    ["name": "Carol", "age": "22"]
]

for user in users {
    guard let name = user["name"],
          let ageString = user["age"],
          let age = Int(ageString) else {
        print("Skipping incomplete user data")
        continue
    }
    
    print("User: \(name), Age: \(age)")
}

Output:

Skipping invalid number: abc

Skipping odd number: 1

Processing even number: 2

Processing even number: 4

Skipping invalid number: xyz

Processing even number: 6

User: Alice, Age: 25

Skipping incomplete user data

Skipping incomplete user data

User: Carol, Age: 22

🧠 Test Your Knowledge

What must a guard statement's else block contain?