- Explain what an optional type (
Int?,String?) andnilare - Unwrap an optional safely with
if letandguard let - Give a default value with
??and use optional chaining with?.
Some of the contacts on your phone have an email address and some don't. A user may type “fifteen” instead of “15” into an age field — and that text cannot be turned into a number. Programs meet such “no value” situations every day. In many languages they cause unexpected crashes, but Swift has a special tool for them — optionals.
What is an optional?
A type that either holds a value of some type or holds nothing (nil). It is written with a question mark after the type name: Int? means “either an Int or nil”.
A plain Int variable can never be empty — Swift guarantees it. If a value might be missing, the type is declared optional. For example, Int("42") tries to turn a string into a number, and the result has the type Int?, because the conversion may fail.
let age = Int("42")
let wrong = Int("hello")
var middleName: String? = nil
middleName = "Ali"
print(age)
print(wrong)
print(middleName)Optional(42)
nil
Optional("Ali")Notice that when an optional is printed, the value appears inside an Optional(...) “box”, and Xcode shows a yellow warning. To use the value in the box, you first have to unwrap it. You cannot simply write age + 1, because you cannot add an Int? and an Int.
Unwrapping with `if let` and `guard let`
if let checks: if there is a value inside the optional, it stores it in a new constant and runs the block; if it is nil, the else block runs. Inside the block, number is already a plain Int.
let input = "15"
if let number = Int(input) {
print("Next year you will be \(number + 1).")
} else {
print("That is not a number.")
}
let nickname: String? = nil
if let nickname {
print("Hi, \(nickname)!")
} else {
print("No nickname yet.")
}Next year you will be 16. No nickname yet.
guard let works the other way round: if there is no value, the else block runs, and it must leave the current code (with return, break or continue). If there is a value, the unwrapped name can be used in all the code after the guard. It is usually used in functions — a function is a named block of code that you will study in detail in a later lesson.
func greet(_ name: String?) {
guard let name else {
print("Hello, guest!")
return
}
print("Hello, \(name)!")
print("Your name has \(name.count) letters.")
}
greet("Aysel")
greet(nil)Hello, Aysel! Your name has 5 letters. Hello, guest!
`??` and optional chaining
The ?? operator gives a default value: if there is a value on the left, it is used; if it is nil, the value on the right is used. ?. is optional chaining: it accesses a property or method of an optional only when there is a value, and when it is nil, the whole expression quietly returns nil.
let savedName: String? = nil
let displayName = savedName ?? "Anonymous"
print(displayName)
print(Int("abc") ?? 0)
let email: String? = "leyla@example.com"
let noEmail: String? = nil
print(email?.count)
print(noEmail?.count)
print(email?.uppercased() ?? "no email")
print(noEmail?.uppercased() ?? "no email")Anonymous 0 Optional(17) nil LEYLA@EXAMPLE.COM no email
Notice that email?.count returns an Int?, not a plain Int — if one link in the chain can be nil, the result is optional too. That is why ?. and ?? are often used together.
| Way | What it does | Safe? |
|---|---|---|
if let x = opt | runs the block if there is a value | yes |
guard let x = opt else { … } | leaves the code if there is no value | yes |
opt ?? default | gives a default instead of nil | yes |
opt?.property | accesses only when there is a value | yes |
opt! | force-unwraps; crashes on nil | no |
Key points
- A
T?type holds either a value of typeTornil; plain types are nevernil. if letruns a block when there is a value;guard letleaves the code when there isn't.??gives a default instead ofnil:Int("abc") ?? 0→0.- The result of
?.chaining is also optional. - Force-unwrapping with
!crashes the program onnil— avoid it.
Check yourself
10 questions. Every correct answer earns XP.
Int("25")?