Swift: Optionals
Intro
In the last post I hinted about a concept in Swift called “Optionals”.
In this post we’ll have a look at what an optional is, what so good about it and what the ? and ! means.
@]?&€!”/* Null pointer exception!
Disclaimer: The following section contains Java code, written by me, a Swift-developer who hasn’t seen decent Java code in almost 10 years. Pardon my French.
You might have heard of “null pointer exception” - it’s something that I hear the Java-developers at work mention from time to time at least. This is what happens when you try to operate on a null-object in Java.
Say for example that you’re passing a pointer to an instance of an object to a function, and that function will invoke a method on that instance:
public void accelerate(Car car) { car.hitTheGas(); }
If the calling code isn’t passing an instance of Car, but instead null (or a pointer to a Car instance that isn’t initialized) - the execution will come to an abrupt end because of.. well you guessed it - a null pointer exception.
In order to mitigate this, you can check for null before you go about with your business with said object.
if (c != null) { c.hitTheGas(); } else { // Awww shit we have to handle this case too... }
Objective-C (which used to be my poison) had another approach to handling this: shutting the hell up about it. The first days of ObjC hacking were great I tell you. “Wow - no null pointer exceptions!!”. But I promise you; it’s prone to produce not-so-easily-found bugs at times.
Wouldn’t it be nice if you could trust that the variable, c in this case, could never ever be null? Wouldn’t that be just fucking awesome? Yes it would…
Optional
An optional in Swift is basically the same thing as that variable c we just saw. It can either have a value or not.
You can think of an Optional as a box containing a value or nil. In order to use the value inside the box, you have to “unwrap” it. This can be done nicely (safe) or forcefully (dangerous).
Well “how will that help me then?” you ask…
var bodyArmor: Armor? // bodyArmor is an optional - it can be nil
First off - you have to be explicit when dealing with variables that can be nil. The above example tells the reader that “Aha - the player (or whatever object this might reside in) can either have a body armor equipped or not!“. That’s valuable information right there!
When reading the variable, you have to be explicit about the fact that it’s an optional too: let bodyArmorDefense = bodyArmor?.defense.
var health: Int // Health can't be nil - it can be 0, but never nil.
The above code states that the variable health is an Int and can’t be nil. It’s not optional. So whenever we’re dealing with this variable we don’t have to check for nil, and we don’t have to care about our application crashing because of our code trying to poke on an object that doesn’t exist.
What’s so awesome about the health variable now is that you can’t assign it the value nil. Ever.
health = nil // <- This won't compile!
So you’re supported by the compiler here not to make mistakes.
health = bodyArmor?.healthBoost // <- Won't compile either
Unwrapping
“Force unwraps”
You’re feeling lucky - Maybe you’re past Ballmer peak and you simply don’t give a shit so you don’t want to be bothered with nil-checks. .
health = bodyArmor!.healthBoost // <- Will compile, but also crash during runtime if bodyArmor is nil.
This is called a forced unwrap of an optional. And basically you should always try to avoid it if possible since this will crash your app if bodyArmor in this example is nil.
“Safe unwraps”
Say we have an optional holding a potential JSON-object.
let json: Json?
And we’d like to execute a function on that object:
json?.doSomething()
If json is nil - nothing will happen (like Objective-C nil-handling)
If json isn’t nil, the method doSomething is invoked
Even though this will “fail silently” it’s still better than Objective-C because we’re explicit about the fact that json can be nil here - we know it’s a valid scenario.
Another great way of safely unwrap options are if let and guard let - more about those another time!
Summary
Be explicit in your code.
Try to not use optionals.
Errors during compile time is better than errors in runtime.
If that fails; try to unwrap safely “?”.
If that fails; try again.. find a way to not do it forcefully.
If that fails; well ok use the god damn “!” but feel ashamed.
Bonus: A peek under the hood
This is an optional! Look how elegant it is!
// I've stripped this implementation down to get to the gist of it. public enum Optional<Wrapped> { case none case some(Wrapped) }
It’s an enum type, that’s either none or some. If it’s some - it also contains an “associated value” (another concept that we’re not going to go deep in to right now, but see it as a value that’s attached to the enum).












