Amit Bijlani
June 17, 2014
-
5 min read
When Apple introduced Swift they talked about three main things they set out to achieve: safe, modern and powerful. One such power feature is called optional. Most language features exist to solve a problem and naturally optional was created to solve a problem. Let’s explore an example to understand its use and purpose. Assume that you have an array containing apartment numbers that violated their rental agreement (oh yeah, they are in trouble). We need to check if an apartment number exists in that array so we can send them a notice.
let aptNumbers = ["101","202","303","404"]
We can write a very simple function to see if we can find a an apartment number within the array.
func findApt (aptNumber : String, aptNumbers: String[]) -> String {
for tempAptNumber in aptNumbers {
if ( tempAptNumber == aptNumber) {
return aptNumber
}
}
}
The above function takes in two parameters. A string and an array of strings. The first parameter is the apartment number we are looking for and the second parameter is an array of all apartment numbers. Then within the function we iterate over our array storing each apartment number in a temporary variable called tempAptNumber
. We then compare the values and if we find a match we return it. However, the above function is incomplete because we are only returning a value when one is found. What happens when we don’t find a value? We must return something. Ideally, we should return a nil
but we specified String
as our return type. One solution would be to return an empty string:
func findApt (aptNumber : String, aptNumbers: String[]) -> String {
for tempAptNumber in aptNumbers {
if ( tempAptNumber == aptNumber) {
return aptNumber
}
}
return ""
}
The above solution is a failure because we should be able to use an if
statement such as:
if findApt("505", aptNumbers) {
sendNotice()
}
However, that if
statement will never get executed because it always returns a String
value. Moreover, it does not evaluate to a boolean expression. We could compare against an empty string but that defeats the purpose. It would be nice to return a nil
when the apartment number is not found in the array. Changing the last line to return nil
will give us a compiler error because we set our return value to be a String
. This is where optionals come in very handy.
An optional can have two states, a value or a nil. To declare an optional, simply suffix it with a ?
. Let’s rewrite our function above to use an optional.
func findApt (aptNumber : String, aptNumbers: String[]) -> String? {
for tempAptNumber in aptNumbers {
if ( tempAptNumber == aptNumber) {
return aptNumber
}
}
return nil
}
Now we are well equipped to use an if
statement:
let culprit = findApt("404",aptNumbers)
if culprit {
sendNotice();
}
Instead of sending a generic notice, let’s assume we needed to use a function sendNoticeTo(apt: Int)
, where we are sending a notice to a specific apartment number. In that case, we cannot simply pass the constant culprit
.
if culprit {
sendNoticeTo(culprit);
}
Firstly, because culprit
is a string and secondly because it is an optional. As I mentioned above that optionals can either contain a value or nil
. When we created the constant culprit
it was implicitly defined as an optional too since that is the return type of our function.
let culprit: String? = findApt("404",aptNumbers) // inferred type String?
It is important to understand that String
and String?
are not the same. The former can only contain a string whereas the later can contain either a string or a nil. So how do we convert the result of our function to the value of type String
?. You can instruct the optional to provide you with a value if there is one.
let culprit = findApt("404",aptNumbers)
if culprit {
sendNoticeTo(culprit!) // Note the use of the ! operator to unwrap the value to String
}
We are not quite there yet because we need to send an Int
to our sendNoticeTo
function. Besides, we can also combine the two above statements into one:
if let culprit = findApt("404",aptNumbers) {
sendNoticeTo(culprit.toInt())
}
When used as an if let
statement the constant culprit
is assigned the actual value of type String
, which is the same as unwrapping the value using a bang !
operator. Now that culprit
is of type String
we can call the toInt()
function on it. There’s still one issue we haven’t addressed. The function toInt()
returns Int?
which is also an optional. Now we could nest if
statements.
if let culprit = findApt("404",aptNumbers) {
if let culpritAptNumber = culprit.toInt() {
sendNoticeTo(culpritAptNumber)
}
}
Why nest when we can chain function calls. Swift provides what is called optional chaining to make such statements compact:
if let culpritAptNumber = findApt("404",aptNumbers)?.toInt() {
sendNoticeTo(culpritAptNumber)
}
The above ties in very nicely because we chain the call to the function toInt
by using the ?
operator. Since toInt
also returns an optional we can check to see if we received a valid apartment number and then call the function sendNoticeTo
else nothing will happen.
Optionals help save a lot of time and make our code readable and efficient. It might take a little getting used to but once you get the hang of it you would hate to have code lying around that explicitly checks for nils or sentinel values.
While you are waiting for our Swift course to be available, take Amit’s current iOS Development course.
GET STARTED NOW
Learning with Treehouse for only 30 minutes a day can teach you the skills needed to land the job that you’ve been dreaming about.
Get Startednot an ideal example since the the function findApt could simply return a boolean!?
Awesome explanation, Amit! Can’t wait to see the new Swift courses on the iOS track.
Excellent tutorial – the clearest one I’ve seen on optionals. I followed it along in a playground & your explanations together with the error messages in the playground have given me a much better picture of how optionals work & when they might be useful.
You might also like other posts...
Career Advice
August 7, 2022
∙ 9 min read
Front-End vs. Back-End: The Complete Guide
If you're new to coding, you may be wondering what the difference is between front-end vs. back-end. Find your answers in our latest Treehouse blog.
Jason Gilmore
Learn
June 7, 2022
∙ 6 min read
Should I Learn HTML Before Python?
Starting your coding journey and wondering if you should learn HTML before Python? We've got you covered. Keep reading to learn the key differences in our latest blog.
Lindsey Rogerson
Learn
January 18, 2023
∙ 10 min read
How to Use the Browser Developer Tools Console
The developer console can help you debug your front-end web applications. Learn more about the browser developer tools in this quick and simple guide.
Matt West
iOS is the operating system that powers iPhones and iPads. Learn the language, tools and frameworks to build interactive apps on the iOS platform.
Learn more