How to Use Nil Coalescing in Swift

Nil coalescing lets you replace nil with a default value using the ?? operator.

What you’ll build or solve

You’ll learn how to turn optional values into usable defaults with ??. Done means you can remove unnecessary if let blocks and safely handle nil in expressions and assignments.

When this approach works best

Nil coalescing works best when:

  • You want fallback text in a UI label.
  • You need a default number for calculations.
  • You convert optional API data into guaranteed values.
  • You want layered fallback logic across multiple optionals.

This is a bad idea if missing data should stop execution. In that case, use guard let or if let instead of silently providing a default.

Prerequisites

  • Xcode installed
  • Basic Swift syntax
  • Understanding of optionals (String?, Int?)

Step-by-step instructions

Step 1: Use ?? to provide a default value

Nil coalescing uses this syntax:

optionalValue??defaultValue

If optionalValue contains a value, Swift returns it.

If it is nil, Swift returns defaultValue.

Example

varusername:String?=nil
letdisplayName=username??"Guest"

If username is "Alex", displayName becomes "Alex".

If username is nil, displayName becomes "Guest".


Getting a non-optional result

The result type matches the default value. This often gives you a non-optional result:

varscore:Int?=nil
letfinalScore:Int=score??0

finalScore is Int, not Int?.


What to look for

  • The left side must be optional.
  • The default must match the wrapped type.
  • The result is non-optional if the default is non-optional.

Works well after optional chaining:

letemail=user.profile?.email??"No email"

Can be used inside expressions:

letfinalPrice=price- (discount??0)

Use ?? only when a fallback value makes logical sense.


Step 2: Chain multiple ?? for layered fallbacks

You can stack nil coalescing operators.

varnickname:String?=nil
varusername:String?=nil

letdisplayName=nickname??username??"Guest"

Swift evaluates from left to right and returns the first non-nil value.

Order matters:

  1. Check nickname
  2. If nil, check username
  3. If both are nil, use "Guest"

This works well when you have multiple possible sources for the same value.


Examples you can copy

Example 1: Safe UI label

vartitle:String?=nil
letnavigationTitle=title??"Home"

The label always shows readable text.


Example 2: Handling API numbers

structAPIResponse {
varlikes:Int?
}

letresponse=APIResponse(likes:nil)

letlikesCount=response.likes??0
print("Likes: \(likesCount)")

You avoid optional math and keep the UI stable.


Example 3: Fallback after optional chaining

structProfile {
varemail:String?
}

structUser {
varprofile:Profile?
}

letuser=User(profile:nil)

letemail=user.profile?.email??"No email provided"
print(email)

If any part of the chain is nil, the default is used.


Common mistakes and how to fix them

Mistake 1: Using mismatched types

What you might do:

varage:Int?=nil
letfinalAge=age??"Unknown"

Why it breaks:

age is Int?, but "Unknown" is a String.

Correct approach:

letfinalAge=age??0

Or change your model so the types align.


Mistake 2: Hiding required validation

What you might do:

varpassword:String?=nil
letsafePassword=password??""

Why it breaks:

An empty string may bypass validation logic. Missing data should not always be replaced silently.

Correct approach:

guardletpassword=passwordelse {
print("Password required")
return
}

Use ?? only when a fallback value is logically correct.


Troubleshooting

If you see “Value of optional type must be unwrapped,” check that you used ?? or safe binding.

If your result is still optional, confirm the default value is not optional.

If the fallback never runs, verify the original value is actually nil.

If chained ?? operators behave unexpectedly, check the evaluation order from left to right.


Quick recap

  • Use ?? to replace nil with a default value.
  • The left side must be optional.
  • The default must match the wrapped type.
  • The result becomes non-optional if the default is non-optional.
  • You can chain multiple ?? operators.
  • Use guard let instead when missing data stops execution.