Optionals are one of the major language features of Swift. Understanding what they are and how to use them will be crucial if you want to code in Swift. Hopefully, by the end of this article you’ll get a solid grasp of the foundations and you’ll be a happy swifter.
What Are Optionals?
Optionals are just a way of representing a variable that may not have a value. It’s quite common that during the execution of the app some of the instance variables are nil. In objective c we would simply set the variable to nil, and that’s it. In Swift we have a special way of indicating that a variable may become nil during the execution. We append a ‘?’ to the variable type, you must have seen it all over the place.
var myVariable: Int?
We also have a different kind of an optional called ‘implicitly unwrapped optional’. These optionals are marked with an exclamation mark ‘!’.
var myImplicitVariable: Int!
If you try to access an implicitly unwrapped optional, and its value is nil, your app will crash. Why on earth would you use them, you might be wondering. We’ll cover that in the next article.
We’ll cover the basics in this article, and in the next one we’ll cover some details about optionals (enums with generics, class initialisation, failing initialisers…)
Using Optionals
We briefly touched on declaring optionals in the section above. You can declare two types of optionals, normal optionals and implicitly unwrapped optionals:
var myOptionalVariable: Int? var myImplicitVariable: Int!
Well cover implicitly unwrapped optionals a bit later. Let’s just focus on normal optionals.
You can assign a value to your optional variable at any point during the execution of the app (assuming it’s not a ‘let’ 🙂 ). You can also set it to nil, as you would expect:
var myOptionalVariable: Int? = 4 print(myOptionalVariable) // prints: Optional(4) myOptionalVariable = nil
In order to use your optional variable, you will have to unwrap it. Let’s say you want to add two numbers, like so:
var number: Int = 7 var result: Int = number + myOptionalVariable // Won't compile
This code won’t compile. Your Xcode will give you a helpful suggestion:
In our case we can’t add an integer and an optional integer. We need to get to the underlying value of the optional integer. Fetching the real value from the optional is called ‘unwrapping’ and we use the ‘!’ operator to do it. So if we modify the above example, and follow the suggestion from Xcode, it’s all good:
var number: Int = 7 var result: Int = number + myOptionalVariable! print(result) // prints: 11
At first glance this might seem OK, but if your optional value is nil when you try to unwrap it, you will crash. This code will crash, for example:
var myOptionalVariable: Int? var number: Int = 7 var result: Int = number + myOptionalVariable! // Crash
In order to use the optional, we first have to check if it is nil:
var myOptionalVariable: Int? var number: Int = 7 if myOptionalVariable != nil { var result: Int = number + myOptionalVariable! print(result) } else { print("variable is nil") } // prints: variable is nil
This example is a bit verbose, and checking/unwrapping is such a common operation that you have a few options available.
Optional Binding
You might hear of optional binding being referred to as ‘if-let’. With optional binding we’ll check an optional for nil and automatically unwrap it:
var myOptionalVariable: Int? var number: Int = 7 if let unwrappedVariable = myOptionalVariable { var result: Int = number + unwrappedVariable print(result) } else { print("variable is nil") } // prints: variable is nil
If ‘myOptionalVariable’ is not nil, it will be unwrapped in ‘unwrappedVariable’ (of type Int). We can then use this variable in the ‘if’ block. If ‘myOptionalVariable’ is nil, else block will get called.
Guard Statement
There’s a slightly neater way of writing the above code. You can use guard statements to unwrap your optionals:
var myOptionalVariable: Int? var number: Int = 7 guard let unwrappedVariable = myOptionalVariable else { print("variable is nil") return } var result: Int = number + unwrappedVariable print(result) // prints: variable is nil
Using a guard statement to unwrap your optionals might not be appropriate at all times. If you can’t proceed if your optional is nil, then it makes perfect sense. For everything else, you have if-let.
Nil-coalescing Operator
Let’s say you want to use a default value for your optional in case it’s nil. You could do something like this:
var myOptionalVariable: Int? var number: Int = 7 var number2: Int = 0 if let unwrappedVariable = myOptionalVariable { number2 = unwrappedVariable } var result: Int = number + number2 print(result) // prints: 7
Knowing what you’ve learned so far, it’s pretty straight forward. But it’s a bit verbose. We can write this much shorter using a ‘nil-coalescing’ operator, or ‘??’:
var myOptionalVariable: Int? var number: Int = 7 var number2: Int = myOptionalVariable ?? 0 var result: Int = number + number2 print(result) // prints: 7
If your optional is nil, nil-coalescing operator will use the default value you provided.
Implicitly Unwrapped Optionals
Implicitly unwrapped optional will automatically unwrap your optional when you access it. If you try to use an implicitly unwrapped optional and it has no value, your app will crash. Just like it would crash if you try to unwrap an optional that’s nil. For example, this will crash your app:
var myImplicitVariable: Int! var useImplicitVariable: Int = myImplicitVariable // Will crash
You might wonder, why would I ever use an implicitly unwrapped optional. Well, perhaps you want your app to crash if a variable is nil. Sometimes it’s better to crash then to run an app in an inconsistent state.
You’ll see a lot of implicitly unwrapped optionals when connecting your outlets in interface builder:
@IBOutlet weak var webView: UIWebView! @IBOutlet weak var errorLabel: UILabel!
If you ever disconnected an outlet and ran your code, you must have seen the crash 🙂
If you don’t want to crash, you’ll have to check your implicitly unwrapped optional for nil. Actually, you can use optional binding, guard statement or nil-coalescing operators with implicitly unwrapped optionals.
Next Week…
I’ll try to keep my articles below 1000 words (around 5 minute reads). So, next week we’ll continue the story with optionals. We’ll go a bit deeper and talk about ‘Optional’ enum, associated values, nil-coalescing operator, optional chaining, initialisers, failable initialisers and other stuff… Stay tuned.
Conclusion
In this article we scratched the surface with optionals. They are a fundamental Swift feature and you simply can’t avoid them. Luckily we have common patterns available to us when working with them. Hopefully you understand them a bit better by now. Stay tuned for next week, when we’ll dive a bit deeper into the subject.
Have a nice day 🙂
Dejan.