fatal error: unexpectedly found nil while unwrapping an Optional value
Have you seen this yet working with Swift yet? If so, you’re not alone. In this post I’m going to dig in to what this means, and explain a bit about optionals in Swift. For those of you who are experienced programmers and have arrived at this page trying to figure out what the error means, here’s the short version:
It means your variable is set to nil, but your code is expecting it to not be nil.
To help understand optionals, let’s open up a Swift REPL. Open up Terminal and boot up the REPL:
swift
Let’s get this error to show up, and analyze what’s happening.
First, create an optional with nothing set:
var username: String?
username: String? = nil
From the REPL it’s clear that username is set to nil, in Xcode it’s not always as obvious. Let’s go ahead and try to use the variable:
print(username)
nil
Okay, confirmed. username is nil. print() understands this and just tells us as much. But, what if we want to make it uppercase using username.uppercaseString? First, let’s try it with a regular ol’ string.
"Jameson".uppercaseString
String = “JAMESON”
Cool, it works. Now let’s try it on username:
username.uppercaseString
error: value of optional type ‘String?’ not unwrapped; did you mean to use ‘!’ or ‘?’?
Oops, we can’t use uppercaseString because it’s not available in the Optional String?
We need to get an “unwrapped” String variable in order to use uppercaseString, because otherwise what we’re seeing is an optional value. Think of this like a “box” we keep values inside of. The box may be empty, or it may contain the value we want. But to be sure, and to work with the internals, we need to force unwrap it by adding an exclamation mark to the end.
username!.uppercaseString
fatal error: unexpectedly found nil while unwrapping an Optional value
Because we tried to force unwrap the optional without ever setting a value to it, we get this error. So what is username? We never set it! This is what the optional type protects from (ourselves)
Optional is actually an enum that contains some information on the variable that’s “inside” it.
When it contains something, the case is ‘Some’, and when it’s empty it’s value is ‘None’. Or in other words.. the Swift compiler is asked to work with what’s inside the box, and if it’s empty, it’s case is “None”. Otherwise, it’s case is “Some” with an associated value, like a username.
So what should you do about it? It’s pretty simple, just use optional binding. This unwraps an optional safely and allows us to execute a block of code *only* if the optional actually contained a value. It looks like this:
if let username = username {
print(username)
}
If you type this in to the REPL, you’ll see nothing happen. Why? Well, because username is “None”! It contains nothing. Try it again with a value set:
let username: String? = "jquave"
if let usernameUnwrapped = username {
print(usernameUnwrapped)
}
jquave
So there you go. Just use optional binding! If you want to unwrap a bunch of variables before proceeding, you can chain these bindings together with commas. So for example if we had to get both a username and password it would look like this:
let username: String? = "jquave"
let password: String? = "romneycomeback"
if let usernameUnwrapped = username, let passwordUnwrapped = password {
print(usernameUnwrapped)
print(passwordUnwrapped)
}
If you’re interested in learning more about Swift, be sure to subscribe to my mailing list for updates. I also recently released a complete Swift 3 Fundamentals Tutorial that covers the language in greater detail.
Thank you for the tips
Just want inform you that Apple removed a method you used on this tutorial
“Swift’s native String type no longer has an uppercaseString or lowercaseString property. The corresponding section in Strings and Characters has been removed, and various code examples have been updated”
Thanks! Updates coming soon for many of these posts.
Can you please write down how to handle this error?
Well, the way to handle it depends on the situation. In general though, what you need to do is check that the variable is not nil before you unwrap it.
So if you had this error on a variable called myAwesomeVariable, you would want to say something like:
if myAwesomeVariable != nil {
// do stuff
}
or:
if let var = myAwesomeVariable {
// do stuff
}
Great stuff
So basically, it just forces you to check if the variable has value or not. if not, you will get nil, if has value, you can do something with it. Am i understand right ?
Yeah pretty much. Nil means empty, no value.
Thanks so much, this helped me to understand optionals a lot better. I have used such code as you suggest in other apps. My situation with my game (first game) is that I can’t see WHAT exactly the debugger is finding nil. Every place I’m checking it says “Value of type SKNode can never be nil, comparison isn’t allowed”.
Is there a simple way to see which variable it is finding nil? The game plays correctly for a while and then crashes at some point when it finds nil.
Christopher
The best approach really is not simply never use the ! operator, unless you know for sure the variable isn’t nil. So for example this is a correct usage:
if (myName != nil) {
displayName(myName!)
}
It is okay here because you’ve done a nil check before this line of code. Even so, it’s still recommended to instead use shadowing to simply replace the variable with the unwrapped optional, like this:
if let myName = myName {
displayName(myName)
}
else {
// Handle the nil optional
}