if let vs guard let vs ?? vs force unwrap — when is each one OK?

1.2.3 · L1 · Interview

Predict first

Does this compile?

func show(_ s: String?) {
    if let s { print(s) }
    print(s.count)
}
  • Yes
  • No

Mental model. guard let is a bouncer at the door: no ticket, no entry, and the rest of the room can relax. if let is a side room you only enter when you have a ticket.

if let x { ... } binds x only inside the true branch — use it when the nil case is a normal branch among several.

guard let x else { return } binds x for the rest of the enclosing scope and must exit on failure. Use it at the top of a function to flatten the happy path.

?? supplies a default and always produces a non-optional. Use it when a sensible fallback exists.

! is only defensible when you can prove the invariant within one screen: an @IBOutlet after viewDidLoad, or a value you just constructed non-nil. Never force-unwrap network or JSON data — that is exactly where the unexpected lives.

if let unwraps only inside its braces. Outside, s is still String?. guard let is the one that keeps the unwrapped name for the rest of the scope.

if letguard let??!
Unwrapped name livesinside the bracesrest of the scopeno name, just a valuethat expression
When nilruns elsemust exituses the defaultcrashes
Best foroptional workpreconditionssensible defaultsproven invariants

Common traps

  • Writing if let x = x on modern Swift. Since Swift 5.7 the shorthand is if let x { }. The long form still works but reads as dated.
  • Using ?? to hide a real failure. A silent default can turn “the server did not send a token” into “we sent an empty token” — much harder to debug.

They might follow up with

  • What is guard required to do? Exit the scope: return, throw, break, continue, or call a Never function.
  • Can you guard let multiple values? Yes, comma-separated: guard let a, let b, a < b else { return }.

Related questions

  • 1.2.4 What does guard buy you beyond if?
  • 1.2.6 How does optional chaining (a?.b?.c) actually work?
  • 1.2.2 Why can switch on an Optional use .none / .some and also nil?

← Why can switch on an Optional use .none / .some and also nil?   What does guard buy you beyond if? →