Note: A lot has changed since this post first went live. If you’re looking for more up-to-date coverage, consider checking out the Cookbook.
Optional values are an foundational concept in Swift. Any variable marked with “?” may–or may not–contain a valid value. To get a sense of this feature, look at the following code.
var soundDictionary = ["cow":"moo", "dog":"bark", "pig":"squeal"] println(soundDictionary["cow"]) // prints moo println(soundDictionary["fox"]) // what does the fox say?
What sound does the fox say? In the case of Swift (not to be confused with Ylvis’s implementation), the answer is nil. In Swift, nil indicates “no value”. Unlike Objective-C, nil is not a pointer. Swift nil indicates a semantic missing non-existance. A count of Monte Cristo. A cup of “not tea”. An honest politician. A nil item means “nothing to see here, move along, move along, move along”.
This soundDictionary example is a string dictionary. Keys are strings, values are strings. If you look up any item, however, the value returned is not a String. Instead, it’s typed String?. That question mark is important. It indicates an optional type. Take a look at the following example. In these lines, I’ve removed the print requests, allowing the Playground to display the value of each item.
Instead of returning “moo” and nil, this example actually returns {Some “moo”} and that nil. Optional types always return either a wrapped value (the bit with the braces) or nil. Wrapping means the actual value is stored in a logical outer structure. You cannot get to that value (in this case “moo”) without unwrapping it. In Swift world, it is always Christmas, and there are always presents — or at least variables — to unwrap.
You unwrap values by adding exclamation points. If the value is wrapped (that “Some” result you just saw) , you receive the value stored within the wrapped element. If the value is nil, you get a fatal runtime error — which is not nearly as fun or gratifying. The nil value is the Swift equivalent of your aunt’s home-crocheted vest. It’s pretty important to always check whether an item is nil before unwrapping it.
You test with one of the many nil checks Swifts provides. The “if let” syntax is the most practical and common. It performs a conditional assignment to an unwrapped variable and executes functionality based on whether it could or could not complete that assignment. In this example if the result is a value, the example uses the (unwrapped) sound variable to print out the animal-sound fact. If nil, it branches to the second half, where there’s no valid value for a sound.
func listen(animal : String) { if let sound = soundDictionary[animal] { println("The \(animal) says \(sound)") } else { println("Any sound the \(animal) says is unknown to modern science") } }
Dictionary lookups more or less always use optional types. The String? type used in the following snippet means that animalSound stores either nil or a wrapped string value, like, for example, {some”Narf!”} — assuming your test sounds come from a Steven Spielberg cartoon.
let animalSound : String? = soundDictionary[searchString]
Swift also provides a feature called implicitly unwrapped optionals. You declare them with an exclamation point at the end of the type. Here’s an example of first a wrapped assignment, and then an implicitly unwrapped one.
With unwrapped optional variables, the result is not {Some “moo”}. It is moo, a simple string. Implicit unwrapping extracts the value inside an optional item and uses the data type you’d expect from the dictionary look-up. Once unwrapped, use the variable directly. You don’t have to add that “unwrap this variable” exclamation point.
Use implicit unwrapping when you know in advance that a variable will always have a value after some logical point. For example, if you’re responding to button taps or menu clicks, you probably don’t have to wonder “does this button or menu item exist?” It does. Because if it didn’t you would never have reached your callback.
Unwrapped optionals enable you to access values directly without having to test and annotate them at each use. With great unwrapping, however, comes great responsibility. You must take care that you properly guard these items to ensure you don’t attempt to unwrap nil.
6 Comments
Great article. Thanks for sharing.
Thank you for taking the time to write this article! It was a pleasure to read, and very informative as well! I am brand new to iOS/Swift development and I ran into some errors while following a tutorial from another site. This article helped me see past these errors and come to understand a useful feature of the Swift language. Cheers!
In Swift 2.0 optionals are used more for failed lookups (dict[key]) and less to return from a failed function (error throwing).
Good Guide! Thank U 🙂
This helped a lot. Thanks for putting it together!
Very good explanation of wrapping and unwrapping.