Skip to content
AgileLogics
7 min read

Unwrapping Optionals Safely

Prerequisites: Optionals

There are several ways to get the value out of an optional. Choosing the right one is a daily Swift skill.

if let — use it if it's there

let input = "42"

if let number = Int(input) {
    print("You entered \(number)")
} else {
    print("That's not a number")
}
You entered 42

Inside the braces, number is a plain Int. When unwrapping a variable into a constant with the same name, Swift 5.7+ has a shorthand:

let nickname: String? = "Addy"

if let nickname {
    print("Hi, \(nickname)")
}
Hi, Addy

guard let — exit early if it's missing

guard checks a condition and must leave the current scope (usually with return) if it fails. After the guard, the unwrapped value is available for the rest of the function:

func greet(_ name: String?) {
    guard let name else {
        print("No name given")
        return
    }
    print("Hello, \(name)!")
}

greet("Ada")
greet(nil)
Hello, Ada!
No name given

guard keeps the main code un-indented: handle the problem cases at the top, then write the normal path. (Functions have their own lesson shortly.)

?? — provide a default

The nil-coalescing operator gives a fallback value:

let savedName: String? = nil
let name = savedName ?? "Guest"
print(name)

let quantity = Int("abc") ?? 1
print(quantity)
Guest
1

! — force unwrap (use sparingly)

! takes the value out without checking. If the optional is nil, the program crashes:

let value = Int("forty")!
Fatal error: Unexpectedly found nil while unwrapping an Optional value

Only force unwrap when nil is truly impossible and a crash would mean a programming error — for example, URL(string: "https://swift.org")! with a hard-coded, known-good address.

Which to use

Situation Use
Do something only if the value exists if let
Can't continue without the value guard let
A sensible default exists ??
nil would be a bug in your own code !

Practice

Write a function parseAge(_ text: String) -> Int that returns the age if text is a valid number, or 0 otherwise. Call it with "36" and "abc".

Show solution
func parseAge(_ text: String) -> Int {
    Int(text) ?? 0
}

print(parseAge("36"))
print(parseAge("abc"))
36
0