In an earlier article, I defined how variables are outlined in Swift utilizing let and var. Each constants (let
) and variables (var
) in Swift at all times have a sort; it is what makes Swift a strongly typed language.
For instance, we might outline a String
variable like this:
// the compiler will know myString is a String
var myString = "Hi there, world"
// we're explicitly telling the compiler that myString2 is a String
var myString2: String = "Hi there, world"
This fashion of defining variables makes a whole lot of sense when it is doable to instantly assign a worth to our variable.
Nonetheless, typically you will write code the place it is not doable to assign a worth to your variable instantly. Otherwise you’re working with features which will or might not be capable of return a sound worth.
In Swift, we name values that may distiguish betwene having a worth and never having a worth an Non-obligatory
. Earlier than we dig too deeply into how we work with optionals, let’s discover the distinction between “no worth” and “default” worth in order that we perceive precisely why optionals exist within the first place.
In the event you choose to study by means of video as a substitute of textual content, try this video on my YouTube channel
The distinction between a default worth and no worth
In programming, working with an idea referred to as null
or as Swift calls it nil
will typically imply {that a} variable or a operate’s return worth could be “nothing”. There’s a whole lot of technical baggage surrounding the terminology however with a view to set up a very good working information, we can’t dig into that too deeply.
The vital factor to grasp right here is that defining an empty String
like this: var myString = ""
defines a String
with a default worth. The worth is empty however the var myString
is holding on to some information that can symbolize an empty String
. Usually this can be a completely fantastic alternative.
Now let’s take into account a special instance the place a default worth could be so much tougher to outline.
var theUser: Consumer = ???
Our Consumer
object cannot be created with out enter from different sources. And this enter won’t be current at the moment that we outline our variable. We’ll want a solution to outline this var theUser
with no information relatively than a default worth.
An actual world analogy you may consider is the next. If you sit down at a restaurant for some drinks, you’ll initially don’t have any glasses or cups in your desk. In consequence, your waiter will know that you have not been served something in any respect in order that they’ll know to go over and hand you a menu, introduce themselves and see whether or not they can take any orders. As soon as you’ve got been served you might need some empty glasses in your desk. The waiter will now know to ask to refill or take a special order.
It is a demonstration of how no worth (no glass on the desk) and an empty worth (empty glasses on the desk) can have important variations in which means and so they cannot at all times be used interchangeably.
In Swift, we specific the flexibility of a property having no worth relatively than a default worth by defining an elective Consumer
object:
var theUser: Consumer?
The ?
after our Consumer
tells the compiler that var theUser
will both include a worth of kind Consumer
or it should maintain nothing in any respect (we name this nil
).
It is good to know that the ?
is a extra handy to put in writing the next:
var theUser: Non-obligatory
Whereas the 2 methods of defining theUser
do the identical factor, it is best follow to put in writing var theUser: Consumer?
. It is simpler to learn and quicker to put in writing.
Observe that every one varieties in Swift could be written as an elective. For instance, for those who’re defining a String
which may have to be initialized as “no worth” you possibly can write: var theString: String?
.
The primary distinction between “no worth” and “default worth” is usually whether or not there’s any semantic which means to pointing at nothing or pointing to a default worth. For instance, an elective Bool
(Bool?
) nearly by no means is sensible; in most situations it is possible for you to to choose a smart default worth that is secure to make use of. In different circumstances, one thing being empty or lacking might point out that enter from the person is required, or that you might want to fetch information from an exterior supply and it is not doable or affordable to supply a default worth.
Now that you know the way to put in writing elective properties, let’s examine how optionals are utilized in Swift.
Utilizing optionals in your code
As soon as you’ve got outlined an elective worth in Swift, it is vital that we deal with the potential of a worth being nil
in addition to the worth being non-nil
. Swift is fairly strict about this so optionals aren’t utilized in the identical manner as you’ll use regular variables or constants.
For instance, if we take into account the theUser
variable from earlier, we won’t learn the identify from this property like this:
var theUser: Consumer?
// Worth of elective kind 'Consumer?' should be unwrapped to confer with member 'identify' of wrapped base kind 'Consumer'
print(theUser.identify)
The Swift compiler will inform us that we have to “unwrap” worth of elective kind Consumer?
with a view to entry its member identify
. That is the compiler’s manner of telling us that theUser
might or might not be nil
so we have to deal with each situations.
Let’s check out severals methods wherein we are able to “unwrap” our elective.
Unwrapping with if let
If we’re writing code the place we need to solely execute part of our script or operate in case the worth is not nil
, we are able to use one thing referred to as an if let
unwrap. This is what that appears like:
var theUser: Consumer?
// some place else within the code...
if let userValue = theUser {
print(userValue.identify)
} else {
print("the person is nil")
}
This if let
makes an attempt to learn theUser
and we assign it to a relentless. This fixed is then made out there inside the if’s physique the place we all know that userValue
is of kind Consumer
. Outdoors of our if physique we can’t be capable of entry userValue
; it is solely made out there inside the if. As wanted, we are able to present an else
to deal with situations the place theUser
is nil
.
Observe that the code above may very well be simplified a bit. Swift permits us to make use of one thing referred to as a shadow variable (variable of the identical identify) for theUser
which might change the if let
as follows:
var theUser: Consumer?
// some place else within the code...
if let theUser {
print(theUser.identify)
} else {
print("the person is nil")
}
Observe that theUser
inside the if physique will not be the identical variable as theUser
exterior of the if physique; it is a completely different property with the identical identify. For that purpose, theUser
inside the if physique is of kind Consumer
and out of doors of the if physique it is Consumer?
. This function of Swift is sweet if you’re conversant in optionals however I discover that typically it is higher to supply a special identify in order that it is clear if you’re utilizing your unwrapped property or if you’re utilizing your elective property.
Unwrapping optionals with guard let
Whereas if let
is nice for utilization inside code the place it does not matter that a lot whether or not a worth is or is not nil
, you typically need to make it possible for a worth is not nil
firstly of a operate. With if let
this could typically imply that you just write an if let
firstly of your operate after which write the entire operate physique inside your if let
:
func performWork() {
if let unwrappedUser = theUser {
// do the work
}
}
This works however it may possibly result in a whole lot of nested code. For situations the place you solely want to proceed in your operate if a worth will not be nil
, you should use guard let
as a substitute:
func performWork() {
guard let unwrappedUser = theUser else {
return
}
// do the work
// unwrappedUser is out there to all code that comes after the guard
}
A guard
permits us to make sure that our person has a worth and that the unwrapped worth is out there to all code that comes after the guard
. Once we’re utilizing a guard
we should present an else
clause that exits the present scope. Often which means we put a return
there with a view to bail out of the operate early.
Unwrapping a number of properties
Each if let
and guard let
permit us to unwrap a number of properties directly. That is performed utilizing a comma separated checklist:
if let unwrappedUser = theUser, let file = getFile() {
// we've entry to `unwrappedUser` and `file`
}
The syntax for guard let
is identical however requires the else
:
guard let unwrappedUser = theUser, let file = getFile() else {
return
}
// we've entry to `unwrappedUser` and `file`
Observe that writing your code like it will require all unwraps to succeed. If both our person or file could be nil
within the instance above, the if physique would not be executed and our guard
would enter its else
situation.
Studying by means of elective chaining
If you’re working with an elective and also you’d prefer to get entry to a property that is outlined in your object, you possibly can write an if let
after which entry the property you are excited about. You noticed this earlier with Consumer
and its identify
property:
if let theUser {
print(theUser.identify)
}
If we all know that we’re solely within the identify
property we are able to use a method referred to as elective chaining to instantly entry the identify
property and assign that to the property we’re writing the if let
for as a substitute.
This is what that appears like
if let userName = theUser?.identify {
print(userName)
}
That is very handy once we’re in a state of affairs the place we actually solely care a few single property. If both theUser
is nil
or (if identify
is elective) identify
is nil
the if physique will not be executed.
We will use this system to entry bigger chains of optionals, for instance:
if let division = theUser?.division?.identify {
}
Each theUser
and division
are optionals and we are able to write a sequence of entry utilizing ?
after every elective property. As soon as any of the properties within the chain is discovered to be nil
the chain ends and the result’s nil
.
For instance, if we simply assign the chain from above to a property that property is a String?
// division is String?
let division = theUser?.division?.identify
The identify
on the division property does not must be a String?
however as a result of we’re utilizing elective chaining we’ll get a nil
worth if both theUser
or division
is nil
.
This leads me to at least one final technique that I might suggest for working with and that is utilizing the nil coalescing operator.
Unwrapping optionals utilizing nil coalescing
For any elective in Swift, we are able to present a default worth inline of the place we entry it. For instance:
let username: String?
let displayName = username ?? ""
The ??
operator within the instance above is known as the nil coalescing operator and we are able to use it to supply a default worth that is utilized in case the worth we’re making an attempt to entry is nil
.
That is significantly helpful when you might want to present values to render in a person interface for instance.
You can even use this system together with elective chaining:
// division is String
let division = theUser?.division?.identify ?? "No division"
Now, let’s check out one final technique to unwrapping that I am solely together with for completeness; this strategy ought to solely be used as a final resort in my view.
Power unwrapping optionals
In the event you’re 100% completely positive that an elective worth that you just’re about to entry can by no means be nil
, you possibly can pressure unwrap the elective when accessing it:
print(theUser!.identify)
By writing an !
after my elective variable I am telling the compiler to deal with that property as non-optional. Because of this I can simply work together with the property with out writing an if let
, guard let
, with out elective chaining or with out utilizing nil coaslescing. The main draw back right here is that if my assumptions are mistaken and the worth is nil
in spite of everything my program will crash.
For that purpose it is nearly at all times most well-liked to make use of one of many 4 secure approaches to unwrapping your optionals as a substitute.