Optional Types

http://lithium3141.com/blog/2014/06/19/learning-swift-optional-types/

“But wait,” you say, “Int is a value type, not an object! How can I use nil for a value?…”

Well, you’re right. NSInteger didn’t have a nil value (or, rather, using nil with the right coercion would get you an integer with a value of 0).

Instead, we defined a ton of marker values that meant “no value:”: 0, 1, NSIntegerMin, NSIntegerMax, and NSNotFound all mean “nothing” in some API.

When you stop to think about it, this is really a limitation: by not having a consistent, defined way of saying no integer value, we’re layering a tiny bit of additional complexity around any use of such a value, then attempting to paper over it with documentation. Want to find an object in an array? Well, if that object doesn’t exist, you get NSNotFound – but if you try to find a nonexistent row in a table view, you get -1 instead.

Swift defines a new type called Optional that always has exactly one of two values: a defined “nothing” value called None, or a wrapped-up value of some other type T.

It’s as if Swift can take regular values and place them inside a box, which may or may not be empty:

In this example, the first integer is a plain Int type.

The second and third, though, are both of type Optional – or, for short, Int?.

Notice that the third value here is actually an “empty box” (the None value), even though its type is Int?.

This ability, to pass around None anywhere an optional type can go, is how Swift can provide things like nil for value types like Int (or, for that matter, any type, whether value or reference). Since this value will have the same type as a “real” value wrapped up in Optional, they can both be represented in the same variable without trying to rely on special values to stand in for the concept of “no value.”

Given:

We need some way of getting at the value inside an optional’s box – and, for that matter, checking whether such a value exists at all! Thankfully, Swift has us covered with the ! operator, which extracts the value out of an optional:

This works great for optionals that have a value. But what about those that don’t?

The ! operator only applies to optionals that have an actual value inside them. If your optional has nil (an alias for .None), it can’t be unwrapped and will throw a runtime error.

Let’s make our code a bit smarter. Instead of unconditionally unwrapping our optional value, we can check whether the value is nil first – much like we might have done in Objective-C.

Not very good way of checking whether the value is nil

Swift has us covered here too, with a syntax called optional binding. By combining an if and a let statement, we can write a concise one-line check for a newly-bound variable that is only conjured into existence if there’s a real value to go along with it:

Chaining – calling methods on those variables

Your program might have some custom classes – most do, after all – and you could want to call a method on an variable that might be an instance, or might be nil.
Developers can make use of optional chaining to call methods on potentially-nil objects:

By sticking a ? between the variable name and method call, we can indicate that we want either a real answer back (in the event that y is a valid instance) or another nil (in the case that y is itself nil).

Even though someMethod() is declared to return an Int, z gets type Optional because we used optional chaining to call the method.

This might seem like a hassle, but can actually be helpful, especially when combined with optional binding from above. If we stick with the same class definition, we can try something like this:

This remains concise while still dealing with all the various concerns we might have:

If y is nil (as it is here), the optional chaining will still allow us to write this code without a type error.

If y is nil or someMethod() returns nil, the optional binding will catch that case and avoid giving us a nil value for non-optional z.

In the event we do get a z, we’re not required to hand-unwrap it because it’s optionally bound.

All in all, this is a pretty clean system for passing around nil values for just about any type. We get some extra type safety out of the deal, avoid using specially defined values, and can still be just as concise as Objective-C – if not more!

Rough Edges

Unary ? operator – Not valid for Swift 3.

It’s valid Swift to take an optional variable and throw a ? at the end (Not for > Swift 3). However, unlike the unwrapping operator !, appending ? doesn’t actually affect the variable in any way: it is still optional.

Surrounding if checks will still look to see if the variable is nil, rather than evaluating its contained truth value (if any).

This can cause extra trouble when combined with Optional Bool

Since the Optional type is defined using generics (it can wrap any other type in the language) it’s possible to construct an optional boolean variable. In fact, it’s virtually mandatory the language allow this: to special-case Bool to disallow optionals would be an exceptional change, requiring serious modifications to the language or the Optional type.

That does, however, lead to a way developers can construct a kind of three-state variable: an Optional can be true, false, or nil. (What the latter means is rather context-dependent.) This can be very misleading, though, when combined with an if check: