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).












