Optional Chaining Explained in Swift
The proper way to send a message to an Optional!
This article assumes you know what a Swift Optional is and how to unwrap it. If this is not the case then read the following before you proceed.
In Swift, you cannot send a message to a value wrapped by an Optional.
import Foundation
let optionalString: String? = "hello world!"
let capitalize = optionalString.capitalized // Error: Value of optional type 'String?' must be unwrapped to refer to member 'capitalized' of wrapped base type 'String'
In this code, the constant optionalString is an Optional that wraps the String “hello world!” The .capitalized instance property is called on optionalString and the result is assigned to the constant named capitalize.
This operation causes the following error:
// Value of optional type 'String?' must be unwrapped to refer to member 'capitalized' of wrapped base type 'String'
This error happens because .capitalized is an instance method for String types, but optionalString is of type Optional String, which is completely different from (the normal) String.
To successfully send the message, you must first unwrap the Optional.
import Foundation
let optionalString: String? = "hello world!"
let capitalize = optionalString!.capitalized
print(capitalize) // output: Hello World!
To unwrap the Optional place an exclamation mark (!) before the dot-notation.
This is known as Optional-chaining.
However, for this to work, you must be sure that the Optional contains a value because if it doesn’t the program will crash.
import Foundation
let optionalString: String? = "hello world!"
let capitalize = optionalString?.capitalized
print(capitalize) // output: Optional("Hello World!")
For times of Optional uncertainty, replace the exclamation mark with the question mark (?) shorthand.
Notice that the output is a capitalized Optional String rather than a String. In other words, the Optional has been unwrapped Optionally — a conditional unwrapping. This effectively tests that the Optional is not nil.
This code reads as, if the Optional contains a String, unwrap the Optional and send the String the .capitalized message, but if it equates to nil, do not unwrap and do not send a message.
This is a graceful way of dealing with an Optional-chaining that may or may not wrap a value. In this example, the Optional contains a String value, but if it was nil the program wouldn’t crash.
You’ll also notice that Optional chain unwrapping works differently from regular Optional unwrapping because the result is a Capitalized Optional String rather than a Capitalized String.
So, to use the result you have to unwrap it.
print(capitalize!) // output: Hello World!
To do this, follow the constant name with an exclamation mark.
Now, the output is a Capitalized String.