Swift
Swift programming
optional variables
Swift syntax
Swift language features

Swift variable decorations with ? question mark and exclamation mark

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

In Swift, ? and ! around variables indicate optional behavior and unwrapping semantics. Understanding the difference is critical for writing safe code and avoiding runtime crashes. Most confusion comes from when to use optional values, forced unwraps, and implicitly unwrapped optionals.

Optional Values with Question Mark

A variable declared with ? may hold a value or nil.

swift
1var nickname: String?
2nickname = "Sky"
3print(nickname as Any)
4nickname = nil

You must unwrap optional values before using them as non-optional types.

Safe Unwrapping Patterns

Use if let, guard let, or nil-coalescing to access optional values safely.

swift
1let name: String? = "Ava"
2
3if let unwrapped = name {
4    print("Hello, \(unwrapped)")
5} else {
6    print("No name")
7}
8
9let displayName = name ?? "Guest"
10print(displayName)

Safe unwrapping prevents runtime failures and makes intent explicit.

Exclamation Mark for Forced Unwrap

! after an optional value forces extraction. If value is nil, app crashes.

swift
let value: Int? = 5
let exact: Int = value!
print(exact)

Forced unwrap is acceptable only when nil is truly impossible by design and validated by control flow.

Implicitly Unwrapped Optionals

Declaring with ! type means value is optional internally but accessed like non-optional until nil appears.

swift
var titleLabel: String!
titleLabel = "Welcome"
print(titleLabel)

This is common in UIKit outlets that are connected after initialization, but should be used carefully.

Optional Chaining

Use ? during member access to continue safely when intermediate value is nil.

swift
1struct User {
2    var address: Address?
3}
4
5struct Address {
6    var city: String
7}
8
9let user = User(address: Address(city: "Toronto"))
10let city = user.address?.city
11print(city as Any)

Optional chaining helps keep nested access concise and safe.

Best Practice Guidance

Prefer ordinary optionals with explicit unwrapping. Reserve implicitly unwrapped optionals for lifecycle-dependent properties where initialization timing is guaranteed. Avoid forced unwraps in business logic paths unless a precondition enforces non-nil state.

Clear optional handling improves code review quality and reduces crash risk.

Optional Use in Real App Models

Optionals are most effective when they model true absence, such as optional profile fields or delayed network data.

swift
1struct Profile {
2    let id: String
3    let nickname: String?
4    let avatarURL: URL?
5}

This communicates domain truth and avoids fake placeholder values.

Guard Let for Early Exit Flow

guard let is ideal when required values must exist before continuing.

swift
1func send(message: String?, to userId: String?) {
2    guard let message, let userId else {
3        print("Missing required data")
4        return
5    }
6
7    print("Send \(message) to \(userId)")
8}

Early-exit style keeps core logic readable.

Avoid Force Unwrap in Async Paths

Values that looked non-nil earlier can become nil after async state changes. Forced unwrap in callbacks is a frequent crash source.

Prefer safe binding near point of use, especially in view lifecycle and network completion handlers.

Interface Builder Outlets and IUO

Implicitly unwrapped optionals are common for outlets because values are injected after initialization.

swift
@IBOutlet weak var titleLabel: UILabel!

Even then, treat IUO as a narrow interoperability feature rather than a general coding style.

Optional Design Guidelines

A practical rule: default to ordinary optional with safe unwrap, use non-optional when value is guaranteed by constructor, and reserve IUO for framework wiring cases only.

Crash Prevention Culture

Treat optional handling as part of app stability strategy. Many production crashes in Swift apps are still caused by force unwrap in edge-case states. A code review checklist that flags unsafe unwrapping in non-test code can reduce crash rate significantly.

Common Pitfalls

  • Using forced unwrap in paths where value can be nil.
  • Declaring too many implicitly unwrapped optionals by default.
  • Ignoring optional chaining and writing verbose unsafe unwrap sequences.
  • Converting optional APIs to non-optional prematurely.

Summary

  • ? declares optional values that may be nil.
  • ! forces unwrap and can crash if value is nil.
  • Use if let, guard let, and nil-coalescing for safe access.
  • Keep optional handling explicit for safer Swift code.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.