Sitemap

Optional Explained

8 min readMar 3, 2023

--

Press enter or click to view image in full size

In Swift, an “optional” is a type that represents the possibility that a value might be nil (i.e., have no value at all).

Here’s an example to help illustrate this concept: Let’s say you’re building an app that lets users create a profile with their name, age, and email address. When a user creates a profile, they might not enter their email address (since it’s optional). In this case, you would represent the email address field as an optional value in your Swift code.

To declare a variable or constant as optional in Swift, you use the “?” symbol after the variable or constant’s type. For example:

var email: String? // This declares the email variable as an optional String

Underneath the implementation of optional

At a low level, Swift’s implementation of optionals involves wrapping the underlying value in an “Optional” enum. This enum has two cases: “some”, which holds the wrapped value, and “none”, which indicates that the optional value is nil.

Here’s an example of how an optional String value might be represented in memory:

Optional("hello")
-----------------
| some("hello") |
-----------------

nil
------
| none |
------

When you create an optional variable or constant in Swift, the compiler automatically creates an instance of the Optional enum and assigns it to the variable or constant. For example, when you declare an optional String variable like this:

var greeting: String?

Swift creates an instance of the Optional enum with the “none” case, indicating that the value is currently nil. Later, if you assign a value to the variable like this:

greeting = "hello"

Swift creates a new instance of the Optional enum with the “some” case, holding the value “hello”. This wrapped value can then be accessed using optional unwrapping (will discuss later).

Optional enum confirm protocol

Optional enum in Swift conform to several protocols, including the Equatable, Hashable, and ExpressibleByNilLiteral protocols.

  • Equatable: This protocol allows you to compare two values to see if they’re equal. The Optional enum conforms to Equatable because you can compare two optional values using the == operator.
  • Hashable: This protocol allows you to create hash values from your data types, which can be useful in data structures like dictionaries and sets. The Optional enum conforms to Hashable because you can create hash values from optional values.
  • ExpressibleByNilLiteral: This protocol allows you to create instances of a type using the nil literal. The Optional enum conforms to ExpressibleByNilLiteral because you can create optional values using the nil keyword.

Here’s an example of how you might use these protocols with optionals in Swift:

let optionalName: String? = "Alice"
let optionalAge: Int? = 30

// Check if two optionals are equal
if optionalName == optionalAge {
print("The name and age are equal")
} else {
print("The name and age are not equal")
}

// Create a dictionary with optional keys and values
let optionalDict: [String?: Int?] = [optionalName: optionalAge]

// Create an optional value using nil
let optionalNumber: Int? = nil

We’re using the Equatable protocol to check if the optionalName and optionalAge variables are equal, the Hashable protocol to create a dictionary with optional keys and values, and the ExpressibleByNilLiteral protocol to create an optional value using the nil keyword.

Optionals provides a safe and efficient way to handle values that might be missing or absent. It allows developers to write code that gracefully handles unexpected situations, without crashing or causing other issues.

Unwrapping Optionals

Unwrapping optionals is a way to access the underlying value of an optional type in Swift. When you want to use the value of an optional, you need to unwrap it first, which means checking whether it has a value and then accessing that value.

There are several ways to unwrap an optional in Swift,

Optional binding

Using “if let” and “guard let” are two techniques for safely unwrapping optionals in Swift. Here’s a brief overview of each technique and their pros and cons, along with a real-world example:

Optional binding with “if let”:

This technique allows you to safely unwrap an optional value and use it within a conditional block. Here’s an example:

if let unwrappedValue = optionalValue {
// use the unwrappedValue variable here
} else {
// the optionalValue is nil
}

Pros:

  • Safe way to unwrap an optional and avoid runtime errors
  • Allows you to use the unwrapped value within a conditional block
  • Easy to read and understand code

Cons:

  • Cannot use the unwrapped value outside of the conditional block
  • Can result in nested code blocks if using multiple “if let” statements

For example: Suppose you’re building a social media app, and you want to display a user’s profile picture if they have one. You have an optional user object with an optional profile picture property. Here’s how you might use “if let” to safely unwrap the profile picture:

if let profilePicture = user?.profilePicture {
imageView.image = profilePicture
} else {
imageView.image = UIImage(named: "default_profile_picture")
}

The “if let” statement safely unwraps the profilePicture optional and sets the imageView’s image property to the profile picture if it exists. If the profilePicture is nil, it sets the image to a default profile picture.

Optional binding with “guard let”:

This technique allows you to safely unwrap an optional value and use it throughout the rest of your function or method. Here’s an example:

guard let unwrappedValue = optionalValue else {
// the optionalValue is nil, handle the error here
return
}
// use the unwrappedValue variable here

Pros:

  • Safe way to unwrap an optional and avoid runtime errors
  • Allows you to use the unwrapped value throughout the rest of your function or method
  • Can improve readability by removing nested code blocks

Cons:

  • Requires an early exit from the function or method if the optional is nil
  • Can be less intuitive for some developers

For example: Suppose you’re building a weather app, and you want to retrieve the current temperature from an API call. You have an optional temperature value that’s returned from the API call. Here’s how you might use “guard let” to safely unwrap the temperature:

func displayCurrentTemperature() {
guard let temperature = getCurrentTemperature() else {
showError()
return
}
temperatureLabel.text = "Current temperature: \(temperature)°F"
}

The “guard let” statement safely unwraps the temperature optional and uses it to set the temperatureLabel’s text property. If the temperature is nil, it calls the showError function and returns early from the displayCurrentTemperature function.

Unwrapping Optionals using forced unwrapping

Unwrapping optionals using forced unwrapping involves using the “!” symbol to forcefully extract the underlying value of an optional type in Swift. This is not the recommended way to unwrap optionals, as it can result in a runtime error if the optional value is nil.

let unwrappedValue = optionalValue!
// use the unwrappedValue variable here

Pros:

  • It is a quick and easy way to access the underlying value of an optional if you are sure that the optional has a value.
  • It can be useful in certain situations where you know that an optional will always have a value.

Cons:

  • If the optional value is nil, using forced unwrapping will result in a runtime error, which can cause your program to crash.
  • It can make your code less safe, as you are assuming that the optional will always have a value, which may not be the case.

Forced unwrapping should be used with caution, and only when you are absolutely sure that the optional value will always have a value. It is generally better to use optional binding with “if let” or “guard let” statements, or the nil-coalescing operator, to safely unwrap optionals in your Swift code.

Implicitly unwrapping

Implicitly unwrapping involves declaring an optional type with an exclamation mark (!) instead of a question mark (?). This is a way to tell the Swift compiler that the optional value will always have a value and can be used safely without explicitly unwrapping it every time.

Get Lingeswaran Kandasamy’s stories in your inbox

Join Medium for free to get updates from this writer.

Let’s say you are building an app that uses a third-party library for displaying images. The library provides an optional image view object, which can be used to display the images in your app. You know that the image view will always have a value, as it is provided by the library, so you can declare it as an implicitly unwrapped optional, like this:

import ThirdPartyLibrary

class ViewController: UIViewController {
var imageView: UIImageView!

override func viewDidLoad() {
super.viewDidLoad()

imageView = ThirdPartyLibrary.createImageView()!
view.addSubview(imageView)

// Use the imageView to display images in your app
}
}

Pros:

  • It allows you to access the underlying value of an optional quickly and easily, without having to use optional binding or the nil-coalescing operator.
  • It can make your code more concise and easier to read, as you do not need to use optional binding statements everywhere the optional value is used.

Cons:

  • If the optional value is nil, using implicitly unwrapping will result in a runtime error, which can cause your program to crash.
  • It can make your code less safe, as you are assuming that the optional will always have a value, which may not be the case.
  • It can be difficult to remember which optional values have been implicitly unwrapped, which can lead to bugs and errors in your code.

Implicitly unwrapping should be used with caution, and only when you are absolutely sure that the optional value will always have a value.

Unwrapping Optionals using Nil-coalescing

Nil-coalescing operator involves using the ?? symbol to provide a default value for an optional in case it is nil. This is a way to safely unwrap optionals without the risk of runtime errors or crashes.

let name: String? = nil
let greeting = "Hello, " + (name ?? "Guest")

print(greeting)

Pros:

  • It provides a default value that can be used when the optional value is nil.
  • It allows you to handle optional values safely without the risk of runtime errors or crashes.
  • It can make your code more concise and easier to read.

Cons:

  • The default value used by the nil-coalescing operator may not always be appropriate or useful for your specific use case.
  • If you need to handle multiple optional values with different default values, your code may become less readable.

Optional chaining

Unwrapping optionals using optional chaining involves using the ? symbol to safely access properties or methods of an optional value. This is a way to unwrap optionals without the risk of runtime errors or crashes.

Pros:

  • It provides a safe way to access properties or methods of an optional value.
  • It reduces the need for multiple nested optional bindings.
  • It can make your code more concise and easier to read.

Cons:

  • It can make your code harder to debug, as it may hide errors or exceptions.
  • It may result in a performance hit, as the optional value needs to be checked multiple times.
class Person {
var name: String?
var age: Int?
}

let person: Person? = Person()

if let age = person?.age {
print("The person's age is \(age)")
} else {
print("The person's age is unknown")
}

Above example makes the code more concise and easier to read, while also providing a safe way to access the age property of an optional person instance. However, it is important to handle errors and exceptions properly, and to avoid excessive use of optional chaining, as it may make your code harder to debug and result in a performance hit.

--

--