Image made with https://imgflip.com/
Have you ever struggled with the various “?” and “!” symbols here and there in a Swift code? Or ever found yourself confused about the phrases like “forced unwrapping”, “optional binding”, “nil coalescing”, “implicit binding” or “optional chaining”? You’re in the right place!
Optionals are a powerful feature in Swift language which come to solve the problem of non-existing values. Coming from Java and being passed through the hell of NPEs, I’m truly excited with this feature of Swift.
Image credit www.raywenderlich.com
Optional is just a type in Swift language, nothing fancy. Int and Int? (optional Int) are two different types, if your variable happens to be of type Int you can be absolutely sure it will always have an integer value, and if your variable is of type Int? it will either have an integer value or it will have no value at all (in other words, it will be nil).
Think of optional as a wrapper type. It’s like a gift box which wraps the value inside, and like a real-life box, optional can either contain something or be empty.
An optional which contains integer value of four, as if to write let myOptional: Int? = 4
An optional that doesn’t contain any value, as if to write let myOptional: Int? = nil
The high level idea of wrapping the value inside a box is that we can safely use the box without worrying what’s inside. There’s a powerful functional programming concept behind Swift optionals - the monads. I highly recommend to delve deeper and study monads so you can have a bigger picture of what is this all about. At the end I’ll provide some good sources to start with.
Under the hood optional types are merely an enum with two cases — None meaning no value is set and Some meaning the value is set and it’s the value associated with it.
Ever seen this annoying compiler error when trying to perform some “innocent” operation? At first glance you’re not doing anything wrong, just trying to add two integer numbers, just the first one is an optional but it surely has an integer value, so why compiler keeps complaining?
Well, because compiler doesn’t know how to add a box into an integer. In order to achieve this we need to unwrap the optional, in other words we need to open the box and extract the value inside. For that we put the “!” mark after the variable’s name meaning “I’m sure this box contains something, extract that value and use it”. This is called forced unwrapping. It’s generally a “dangerous” thing to do because if the box is empty the app will crash at runtime. A good practice is to check for nil before unwrapping.
Under the hood forced unwrapping is just a switch statement.
Like forced unwrapping, optional binding is a way of opening the box, but it does the job more cleverly and with less pollution than forced unwrapping. It allows to check the optional and extract its value into a constant or variable as part of a single action. It’s useful when we need to use the unwrapped value many times in the if body.
This will be read as “If the optionalInt has a value, extract that value into the constantInt and use it inside of the if body, otherwise print that it’s nil”. Note that we didn’t use “!” with constantInt, that’s because it represents the already unwrapped value of optionalInt. So we just unwrap it once and can use it multiple times in the if body.
Under the hood optional binding works similar to the forced unwrapping, except in this case it just breaks the switch instead of throwing an exception.
Sometimes we’re really-really sure we’ll always have a value in our optional just after it’s set the first time. In this case there’s no need to unwrap the optional every time we want to use it, because it’s safe to assume we have a value. Implicitly unwrapped optionals come to help in this case, it’s sort of saying “unwrap this guy once and use the value anywhere you want”.
Implicitly unwrapped optionals are declared with the “!” mark in their type. So for the implicitly unwrapped String optional we would have String! as its type.
Note that we’re not using the “!” mark with the assumedInt, because it’s an implicitly unwrapped optional.
Sometimes we want to use a default value when the optional is nil. Let’s take a look at this example:
This could be reduced to a one line by using a ternary operator (the “?” below represents the ternary operator).
Nil coalescing allows us to shorten this even more.
This just means “If optionalInt is nil then use zero, otherwise use its unwrapped value”.
Optional chaining is a feature that allows to call properties and methods on an optional that might currently be nil. Unlike forced unwrapping which would result in a runtime exception, optional chaining fails gracefully when the optional is nil.
Let’s take a look at this example: a person may or may not have a bank account, and a bank account surely has a balance. So if we want to get the balance for a person’s bank account we might need to first check if he/she has a bank account or not, and in case of positive answer get its balance. Here’s where optional chaining and the idea of using the box without opening it come into play.
Instead of putting “!” to unwrap the bankAccount, we put “?” after it to say “If the person has bank account then go ahead and get its balance, if the bankAccount is nil, just return nil as its balance”. Because of this, the result of optional chaining is always an optional. So essentially optional chaining allowed us not to worry about what’s inside the box called bankAccount. If the box is empty, we get an empty box as a result, and if the box has a value, we get the expected result wrapped into another box.
Optionals are not that scary, are they? We just learned that they represent a wrapper type, that they’re like a box wrapping a value, and the box can be opened in 3 different ways
i_mplicitly unwrapped optionals_ (hey, I’m sure I’ll have a value once it’s set the first time, I don’t want to bother unwrapping it everywhere in my code)We learned that we can have a very concise way of using default values in case of empty box due to nil coalescing. And finally we learned about the optional chaining. We learned that we not always need to open the box in order to use it, and that’s the whole beauty of optionals. I didn’t go deep into that topic to talk about map and flatmap, because it will complicate things for beginners (for whom this article is generally targeted), but now when you understand how to deal with optionals, I strongly encourage you to go deeper. There’re some really great sources at the bottom.
References: Swift programming language guide The complete guide to understanding Swift Optionals by Matteo Manferdini. Absolutely recommend to read this short book. You can also subscribe to get Matteo’s other useful guides and articles by email.Developing iOS 9 Apps with Swift — Stanford university course
Sources for understanding optionals as monads:Swift Functors, Applicatives, and Monads in PicturesBrian Beckman: Don’t fear the MonadSome great Quora answersThe Power Of Map And FlatMap Of Swift Optionals
If you have any questions or feedback please don’t hesitate to post them, I will be glad to answer your questions or get your valuable feedback. Have a great time learning Swift!