Optionals

Swift · Essentials · 12 min

Optionals are Swift's answer to null pointer crashes, and nearly every API returns or accepts them.

A normal Swift type can never be nil. To allow absence, use an optional: String? means "a String or nothing". Under the hood it is the enum Optional<Wrapped> with cases .some(value) and .none.

You can't use an optional as if it were the value; you must unwrap it:

  • if let name { ... } — binds a non-optional name inside the block (shorthand for if let name = name).
  • guard let user else { return } — unwraps for the rest of the scope.
  • value ?? fallback — the nil-coalescing operator supplies a default.
  • user?.address?.city — optional chaining; the whole expression becomes nil as soon as any link is nil.
  • optional.map { ... } transforms the value if present.

The force unwrap value! crashes if the value is nil. Reserve it for cases where nil would be a programmer error, and prefer a descriptive guard with fatalError or preconditionFailure when you do.

Many APIs return optionals to signal failure without an error: Int("42") is Int?, and array.first is nil for an empty array. Implicitly unwrapped optionals (String!) exist mostly for interop and Interface Builder outlets; avoid them in new code.

Example

func greet(_ input: String?) -> String {
    guard let input, !input.isEmpty else { return "Hello, stranger" }
    return "Hello, \(input)"
}
print(greet(nil))        // Hello, stranger
print(greet("Mia"))      // Hello, Mia

let port = Int("8080") ?? 80    // 8080
let bad = Int("abc") ?? 80      // 80

struct User { var nickname: String? }
let u: User? = User(nickname: nil)
print(u?.nickname?.count as Any)   // nil

if let n = Int("12") {
    print(n * 2)          // 24
}

Remember

  • T? can be nil; plain T never is
  • Unwrap with if let, guard let, ?? or ?.
  • ! crashes on nil — use it only for true invariants

Watch out for

  • Sprinkling ! to silence the compiler; it moves the crash to run time.

Check yourself

  1. What is the type of `user?.name.count` when `user` is `User?` and `name` is a non-optional String?
  2. Which expression gives 0 when `s` cannot be parsed as an Int?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics/#Optionals

Builds on

Unlocks

Nothing builds on this yet.