In a nutshell Optional is like a box, it can contain a value or it is empty. Under the hood it’s an enum with two cases:
You may wonder why we even need another type to wrap existing ones? We could check in a runtime if the property is nil but many examples from other languages show that it’s a huge source of problems. Sometimes even experienced developer can miss such error not mentioning beginners. Fortunately, Swift prevents assigning nil value to type which isn’t Optional. It almost completely eradicates the problem of unexpected nil values, and make code less error-prone.
Let’s consider a real-life example which will help you understand the concept of optional values. We want to create a simple gallery of photos, first of all, we need to know the number of photos to display. Depending on the source of this photos type of “numberOfPhotos” property may be different.
- If photos are the static content in application we don’t need optional, because at the moment of writing the code we already know the number of photos.
- What if photos are stored on the remote server? We could use some default value like “0” and refresh it after server response, but there is a catch. Sometimes there is no value which could be assigned as a default (for example integer in a calculator app). It can be negative, positive or zero so default value could introduce some nasty errors. Optional is handy because it tells that numberOfPhotos is an integer but could be not available at the moment (contains nil).
- The example above is a valid declaration of Optional integer, but it’s very unpopular. There is a lot simpler way to achieve the same result – just add a question mark after the type and that’s it! 🙂
- The last example shows unconditional unwrapped optional. To put it simply, it’s optional which is already unwrapped at the moment of accessing its value. Use this type of optionals as a last resort, because it will crash the application if the instance of optional contains nil. Personally, I try not to use force unwrapped optionals, in larger projects you don’t have a guarantee that changes made by someone else won’t affect your code and make optional nil.
Safe unwrapping is the simple way of accessing a value of optional without the risk of error. It’s extremely easy task and after a short period of time, it will become something natural and almost unnoticeable during writing the code. There are 3 methods of safe unwrapping which I want to show you:
- If numberOfPhotos is integer this code will execute “if block” and assign value wrapped by numberOfPhotos to constant unwrappedNumberOfPhotos in the scope of this block. If numberOfPhotos is nil, “else block” will be executed.
- Guard statement is reversed if let statement. Else block will be executed if numberOfPhotos is nil otherwise it will assign it’s value to unwrappedNumberOfPhotos in the whole scope below guard statement. Using guard statement often help to avoid many nested if blocks which makes code easier to read.
- As I’ve mentioned before Optional is an enum with two cases, so it can be handled by switch statement.
You can also use “while let” statement instead of “if let” but it’s so uncommon that I’ve decided to skip this method. Generally, I use a combination of first two methods depending on the scope in which I need unwrapped value.
Optional chaining is a very useful feature that drastically reduces the amount of code if there is a complex structure. Instead of many nested „if” blocks, we can chain calls of optional and non-optional values like I’ve done it above „ server.user?.storage?.numberOfPhotos”. Such call will return an integer which represents the number of photos or nil if there is any nil value in the chain of calls. In OOP (Object Oriented Programming) it’s very common to access properties of nested structures so I use that feature a lot. 🙂
As I’ve mentioned earlier when you are 100% sure that instance of Optional is not nil you can use an exclamation mark in order to force unwrap optional. It’s very quick method, but laziness can lead to runtime errors. In many teams, such code won’t be accepted in Code Review so try not to use force unwrapping when it’s not necessary.
Sometimes you can face the situation in which you must provide some default value. Instead of safe unwrapping which involves a lot of additional code, you can use nil coalescing ternary operator „??”. It works very simply – if Optional is nil, it returns the default value instead. In our case if “server.user?.storage?.numberOfPhotos” is nil we assume that we have 0 photos available.
I hope that I’ve managed to show you how simple and useful are optional values. This concept isn’t new and other languages like Kotlin, Java etc. also have it. Swift stands out, because none of them managed to make optionals so simple, intuitive and well integrated like Swift does. There are many different ways to achieve exact same results using optionals so I have one advice. Don’t take my word which solution is the best, but check on your own, which one of them suits your needs the most. You will be shocked how powerful tool you’ve just discovered. 🙂