Swift’s answer to null crashes: a value is either present or nil, encoded in the type. Learn optional binding, guard, nil-coalescing, and optional chaining — the safe ways to work with maybe-missing values.
In Swift a normal type can never be nil; you opt into "maybe absent" with a trailing question mark, making it an Optional. The compiler then forces you to unwrap the optional before using the underlying value, turning null-pointer crashes into compile-time requirements. This is Swift’s equivalent of a null-safety system and eliminates a whole class of runtime failures.
var name: String = "Ada"
// name = nil // ERROR: non-optional String can't be nil
var maybe: String? = "Bo" // '?' makes it Optional<String>
maybe = nil // now allowed
// print(maybe.count) // ERROR: 'maybe' is optional — must unwrap first
// the compiler won't let you use the value until you handle the nil case.To use an optional safely you unwrap it. if let binds the value inside a block when it is non-nil; guard let binds it for the rest of the scope and requires you to exit early otherwise. guard is idiomatic at the top of a function — validate inputs, unwrap, and bail on failure, keeping the happy path unindented below.
func greet(_ name: String?) -> String {
// if let: value available inside the block
if let name = name {
return "Hello, \(name)"
}
return "Hello, guest"
}
func process(_ name: String?) -> String {
// guard let: unwrap for the REST of the scope, else exit early
guard let name = name else { return "no name" }
return "Processing \(name)" // 'name' is non-optional from here on
}Two operators make optionals concise. The nil-coalescing operator ?? supplies a default when the optional is nil. Optional chaining with ?. accesses a property or method only if the value exists, short-circuiting to nil otherwise. Chaining them lets you dig through possibly-missing data and provide a fallback in one readable expression.
let name: String? = nil
let display = name ?? "guest" // ?? -> default when nil
print(display) // guest
let count = name?.count ?? 0 // optional chaining + default -> Int
print(count) // 0
struct User { var address: Address? }
struct Address { var city: String }
let user: User? = nil
let city = user?.address?.city ?? "unknown" // chain through optionals
print(city) // unknownThe ! operator force-unwraps an optional, crashing if it is nil. It exists for the rare case where nil is truly impossible, but it reintroduces the crashes optionals are designed to prevent, so treat it as a code smell. Prefer if/guard let, ??, or optional chaining; reaching for ! usually means the optionality is modeled wrong.
Avoid force unwrap — The ! operator crashes the app if the optional is nil — exactly the failure Swift optionals prevent. Prefer if let / guard let, ??, or optional chaining. Reserve ! for values that are provably never nil.let text: String? = "42"
let number = Int(text!)! // two force-unwraps — crashes if either is nil
// prefer safe alternatives:
if let text = text, let n = Int(text) {
print(n) // 42, safely
}
let safe = Int(text ?? "") ?? 0 // default all the way down
// if you're reaching for '!', the nullability is usually modeled wrong.