So far, we know that optionals wrap values in themselves. Wrapping means that the actual data is stored within an outer structure.
For instance, we print optionalString
as follows:
print(optionalString)
The result will be Optional("A String literal")
.
How will we unwrap optionals and use the values that we need? There are different methods to unwrap optionals that we will go through in the following sections.
To unwrap optionals, the easiest and most dangerous method that we can use is force unwrapping. In short, !
can be used to force unwrap the value from Optional
.
The following example forcefully unwraps optionalString
:
optionalString = "An optional String" print(optionalString!)
Force unwrapping the optionals may cause errors if the optional does not have a value, so it is not recommended to use this approach as it is very hard to be sure if we are going to have values in optionals in different circumstances.
In fact, force unwrapping eliminates the benefits of type safety and may cause our applications to crash during runtime.
Force unwrapping an Optional
could crash our applications; to eliminate the crashing problem, we can check whether the variable is not nil
before unwrapping it.
The following example presents a simple nil
checking approach:
if optionalString != nil { print(optionalString!) }
This approach is safe in compile and runtime but may cause problems during editing. For instance, if we accidentally move the print
line outside the if
block, the compiler is not going to complain and it may crash our application during runtime.
The better approach would be to use the Optional binding technique to find out whether an Optional
contains a value or not. If it contains a value, we will be able to unwrap it and put it into a temporary constant or variable.
The following example presents optional binding:
let nilName: String? = nil if let familyName = nilName { greetingfamilyName = "Hello, Mr. (familyName)" } else { // Optional does not have a value }
The if let familyName = nilName
statement will assign the Optional
value to a new variable named familyName
. The right-hand side of the assignment has to be an Optional
, otherwise, the compiler will issue an error. Also, this approach ensures that we are using the unwrapped temporary version so it is safe.
This approach is also called if-let binding and is useful to unwrap Optionals
and access the underlying values, but if we get into a complex structure of nested objects such as a JSON
payload, the syntax becomes cumbersome.
We will need to have lots of nested if-let
expressions in these cases:
let dict = ["One": 1, "Two": 2, "Three": 3] if let firstValue = dict["One"] { if let secondValue = dict["Two"] { if let thirdValue = dict["Three"] { // Do something with three values } } }
To overcome this issue, we can use multiple Optional bindings as follows:
if let firstValue = dict["One"], secondValue = dict["Two"], thirdValue = dict["Three"] { // Do something with three values }
This syntax makes the code more readable but still is not the best approach when we need to bind multiple levels of optionals. In the following sections, we will look at different methods to further improve the readability and maintainability of our optional handlings.