Continuing our conversations about variables in Swift, lets move on to one of the more important additions in this realm to Swift, Optionals. In Swift, all normal variables must have a value. In Objective-C, C-based variables (primitives) always had to have a value, but object types could either be a valid object, or a pointer to nil. Swift optionals allow you to make any type in Swift into a nil-able type (though this nil is not exactly the same as an Objective-C nil).
The Reason for Swift Optionals
While Swift optionals are new, they have their roots in Objective-C. You could set any pointer based variable to nil like NSString, NSDate, etc. However, you could not do the same with primitive C types like ints, doubles, etc. You would have specific sentinel values to deal with them, which were valid numbers, just not often used. In the case of ints, it was NSNotFound, which was mapped to NSIntegerMax. What if you happened to have a valid value of 2,147,483,647 on a 32-bit system, or 9,223,372,036,854,775,807 on a 64-bit system.
It’s unlikely, but it could be some big-data program, or maybe something displaying the number of neutrinos going through Cupertino during a certain time period, who knows? If you are curious, apparently 65 billion neutrinos pass through one square centimeter of Earth every second (according to Wikipedia), and with Cupertino being 29.16 km², if my math is correct, that comes out to about 487 µsec.
Anyway, that tangent aside, Apple decided to have a single sentinel value to refer to an invalid state, instead if NSNotFound, NSNULL, and many others, they just boiled down to nil, via Swift optionals. So now, you can make any variable, be it an Integer, String, custom class, or even a structure, into a nil-able type. It is actually rather interesting, and surprisingly simple how it is implemented under the hood. To Swift, an optional is just this:
enum myOptional<T> { case None case Some(T) }
It is an enumeration with 2 possible states, None or Some. None handles returning nil for a value, while some actually holds the value. This is a generic enumeration, and if you’re curious how both of those work, check out my future posts Enumerations in Swift and Generic Types in Swift. The “Some” case is using the ability for enums to have values associated with their states, so in the parenthesis you would enter the type of value you would want to associate with that case. So if it would return a String, you would put String in the parenthesis. In this case, it is a generic, so the Optional enum is made of type “T”, which is a placeholder for whatever type is actually specified, and so we put T in as the type for the “Some” case value.
Using Swift Optionals
If you are not sure about something, wouldn’t you ask a question about it? Apparently, Apple thought something similar because that is basically how you declare an optional. Behold:
var optionalInteger: Int? var normalInteger: Int //For Comparison
Seems simple enough. You can then write to it like any other Integer, no special boxing required to set it. As we have already discussed, since it is a Swift optional, you can set it to nil, also with no special boxing.
var optionalInteger: Int? optionalInteger = 42 optionalInteger = nil
The same is not true for reading it though. Swift expects values to be standard, non-optional types, so to actually used them you have to change them back from Swift optionals to standard Swift types. There are a few ways to do so:
Forced unwrapping
One way to use Swift Optionals in places that don’t take them, is to forcefully change them back into normal variables. Apparently you question a variable to make it into an optional, and you yell at at it to forcefully unwrap it:
normalInteger = optionalInteger! + 5
Yep, that exclamation point forcefully unwraps it. There is a problem though. You have to check it for nil before you do this to be safe. If you try this with the optional containing a nil, a runtime error will occur. One way to deal with this, is to check for it in an if statement:
if optionalInteger != nil { normalInteger = optionalInteger! + 5 } else { print("Nothing here") }
Now it will only do the unsafe unwrapping if there is a non-nil value in the Swift optional.
Optional Binding
For this bit of code, that is fine, but what if we had to use optionalInteger more times in that if statement. Would you want to remember to type that exclamation point everywhere? You might forcefully unwrap it and assign it to a temporary normal variable, and that would be much better. What if you could simply do that at the same time you check whether it is a valid Integer?
if let tempInteger = optionalInteger { normalInteger = tempInteger + 12 } else { print("Still nothing here") }
With that “if let” syntax, you do just that, and store an unwrapped version of “optionalInteger” in “tempInteger”, or you skip that condition and go to the else. This is called “Optional Binding.”
Conclusion
There are a few more things to talk about with Swift optionals, but I think this is a good place to start. Check out my next post about Optional Chaining and Implicitly Unwrapped Optionals in Swift, as well as about another way to either unwrap an Optional, or return a default value with the Nil Coalescing Operator in Swift. Optionals are a very powerful tool in Swift, and as such we must be careful, that is, unless we want to cause a runtime error.
Also, released in Swift 2, there is another way to unwrap Optionals, particularly helpful to get return from a method early if a Swift Optional is nil, or an invalid value, the Guard statement. You can read more about it in the post The Guard Statement in Swift 2.
I hope you found this article helpful. If you did, please don’t hesitate to share this post on Twitter or your social media of choice, every share helps. Of course, if you have any questions, don’t hesitate to contact me on the Contact Page, or on Twitter @CodingExplorer, and I’ll see what I can do. Thanks!