Optionals are one of the tricky parts of Swift. Mainly because similar concept is not present in many languages and you need to understand them pretty early on to know what is going on with all these ?
, !
, if let
and similar in the code..
So first things first.
Why
Why have Optionals at all? Other languages can work without them. But they still have to deal with absence of value. This si super important concept. Not everything has value at all time.
So if you are expecting number in a form of an Int
but have no guarantee to get it. How would you represent this? 0
or -1
can work in some context, but this can equally be a valid number.
Enter null
value or rather nil
which Swift uses. Those exist to represent the absence of value and you can find them in Java, C#, JavaScript, Python (in the form of None
) and other languages.
Now you need mechanism to only access the variable if it has value and is not nil
. This is where Optionals come in. To safely deal with absence of value.
What
So what are Optionals? In a nutshell a way to deal with these situations where value may or may not be present. Way to safely access this value or otherwise handle its absence.
I think it is helpful to think about Optionals as kind of boxes. This box can either be empty (nil
) or contain stuff (aka our value). Swift offers us many ways to safely (or dangerously) open that box and then work with just the value.
Behind the scenes Optional is just an enum
with two cases and special compiler support. That is all. The end result is pretty great system for dealing with uncertainty concerning the availability of values.
How
Accessing values from Optionals is called unwrapping. Maybe like unwrapping a present? 🙂
if let
One of the opening techniques is the if let
construct to safely bind the value to non-optional variable.
Suppose we have this Int
variable:
var number: Int? = 4
It is of type Optional<Int>
because instead of 4
it could contain nil
. Swift won’t let you work with number
as it were normal Int
and for example do arithmetics like:
let result = number + 5 // error!
Because what would nil + 5
equal to? Nothing and five as a bonus? :-)
We need to “unwrap” the value first.
if let num = number {
let result = num + 5 // works!
}
If number
has a value, if let
will bind it to num
which will be available in its scope and we can use it as standard Int
.
This is the Swift’s way of preventing runtime crashes, because some variable is nil
and cannot be used.
guard let
Very similar to if let
but the body of the guard
is used to handle situations when optional is nil
and must not “fall through” which means it has to exit the current scope. Usually with return
but you can also use continue
or break
when in a loop.
guard let num = number else {
// number is nil, fallback code
return
}
print(num) // num is no longer optional
Dangerous !
You can use !
operator to circumvent safety and force unwrap the value. This is dangerous because if the variable is nil
your program will crash.
let number: Int? = nil
print(number!) // crash
let number2: Int? = 3
print(number2) // prints 3
It is best to avoid. However !
can be useful in situations you are 100% sure value is present. Maybe because you set the value yourself on the previous line.
Comparing with nil
You can also check optionals for value with standard if
:
if number != nil {
// number is still optional
}
Providing default value
There is yet another useful technique for dealing with Optionals in the form of nil coalescing operator ??
.
let number: Int? = nil
print(number ?? 3)
If the left side is nil
the right side will be used. You can chain this but for the sake of readability I would not recommend it.
Is anything not clear? Do you want more information? Ask in the comments and I will do my best to help you. Thanks for reading!
Top comments (0)