← Swift EnglishChapter 09 of 13

Optionals

## Learning Objectives - Understand what optionals are - Use optional types and unwrapping - Master optional binding - Work with nil coalescing ## What are Optionals? Optionals represent values that may or may not exist: ```swift var name: String? = "Alice" var empty: String? = nil ``` ### Why Optionals? ```swift // Without optionals - unclear if value can be missing // String name = null; // What does null mean? // With optionals - explicit about missing values let name: String? = nil ``` ## Optional Type Declaration ### Syntax ```swift String? // Optional String (may hold String or nil) Int? // Optional Int Double? // Optional Double Bool? // Optional Bool [ String ]? // Optional Array of Strings ``` ### Non-Optional vs Optional ```swift let certain: String = "Hello" // Must have a value let maybe: String? = nil // May or may not have a value ``` ## Forced Unwrapping ### Using (!) ```swift let name: String? = "Alice" print(name!) // "Alice" // WARNING: Crashes if nil! let empty: String? = nil // print(empty!) // RUNTIME CRASH! ``` ### When to Avoid ```swift // BAD - crashes if nil func getUsername() -> String? { return nil } let username = getUsername()! // print(username) // Crash! ``` ## Optional Binding ### if let ```swift let name: String? = "Alice" if let unwrappedName = name { print("Hello, \(unwrappedName)") } else { print("No name provided") } // Output: Hello, Alice ``` ### guard let ```swift func greet(name: String?) { guard let name = name else { print("No name") return } print("Hello, \(name)") } greet(name: "Alice") // Hello, Alice greet(name: nil) // No name ``` ### Multiple Binding ```swift let name: String? = "Alice" let age: Int? = 30 if let unwrappedName = name, let unwrappedAge = age { print("\(unwrappedName) is \(unwrappedAge)") } // Can combine with conditions if let name = name, let age = age, age >= 18 { print("\(name) is an adult") } ``` ## Nil Coalescing ### ?? Operator ```swift let name: String? = nil let displayName = name ?? "Anonymous" print(displayName) // "Anonymous" let actualName: String? = "Alice" let greeting = "Hello, \(actualName ?? "Guest")" print(greeting) // "Hello, Alice" ``` ### Chaining ```swift let nested: String?? = nil let result = nested ?? "default" // "default" let optionalString: String? = "Hello" let result2 = optionalString ?? "nil or empty" // "Hello" ``` ## Implicitly Unwrapped Optionals ### Declaration ```swift var implicitlyOptional: String! = "Hello" print(implicitlyOptional) // No need to unwrap ``` ### Use Cases ```swift class ViewController { var label: UILabel! // Will be set later func viewDidLoad() { label.text = "Hello" // Safe because we know it's set } } ``` ### Dangers ```swift var dangerous: String! = nil print(dangerous) // CRASH! ``` ## Optional Chaining ### Optional Chaining Syntax ```swift let street: String? = address?.city?.street?.name ``` ### Example ```swift class Person { var residence: Residence? } class Residence { var address: Address? } class Address { var street: String = "123 Main St" } let person = Person() let street = person.residence?.address?.street // street is nil (person.residence is nil) // No crash - chain short-circuits ``` ### With Methods ```swift if let length = person.residence?.computeRoomCount?() { print("House has \(length) rooms") } ``` ## Comparing Optionals ### Equality ```swift let a: Int? = 5 let b: Int? = 5 let c: Int? = nil a == b // true a == c // false a == 5 // true (compares to non-optional) c == nil // true ``` ### Optional Enum Case ```swift enum Color { case red, green, blue } let selected: Color? = .red if selected == .red { print("Red is selected") } ``` ## Map and FlatMap ### Optional Map ```swift let number: Int? = 5 let squared = number.map { $0 * $0 } // Optional(25) let nilNumber: Int? = nil let nilSquared = nilNumber.map { $0 * $0 } // nil ``` ### Optional FlatMap ```swift let string: String? = "42" let int = string.flatMap { Int($0) } // Optional(42) let invalid: String? = "hello" let notInt = invalid.flatMap { Int($0) } // nil ``` ## Pattern Matching ### switch with Optionals ```swift let value: Int? = 5 switch value { case nil: print("Is nil") case let unwrapped?: print("Has value: \(unwrapped)") } ``` ### if case ```swift let age: Int? = 25 if case let unwrapped? = age { print("Age is \(unwrapped)") } ``` ## Common Errors ### Unexpected Nil ```swift func getUser() -> String? { return nil } let user = getUser() // user.uppercased() // ERROR: Cannot call on Optional // user!.uppercased() // CRASH: nil value ``` ### Wrong Type ```swift let string: String? = "123" // let number: Int = string // ERROR: Cannot assign String? to Int let number: Int? = string.map { Int($0) } ``` ## Best Practices ### Do ```swift // Use optional binding if let value = optional { use(value) } // Use guard for early exit func process() { guard let value = optional else { return } use(value) } // Use nil coalescing for defaults let result = optional ?? "default" ``` ### Don't ```swift // Don't force unwrap // let value = optional! // DANGEROUS // Don't compare to nil explicitly (prefer optional binding) // if optional != nil { } // Not idiomatic ``` ## Summary - Optionals represent values that may be nil - Declare with `Type?` syntax - Force unwrap with `!` (dangerous if nil) - Optional binding: `if let` and `guard let` - Nil coalescing: `??` provides default value - Optional chaining: `?.` safely accesses properties - `map` and `flatMap` transform optional values - Implicitly unwrapped optionals (`Type!`) defer unwrapping - Prefer safe unwrapping over force unwrap

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →