Solved: Fatal error: Unexpectedly found nil while unwrapping an Optional value
This question comes up ALL THE TIME on SO. It's one of the first things that new Swift developers struggle with.
What is an Optional (background) ?
In swift an optional is a constant or variable that can hold a value OR no valuenil
of the original type. This value is denoted by "?". An optional value must be unwrapped.
So in other words an optional, is actually a container or wrapper.
The "!"
operator is a force unwrapper which exposes whats in the container. It says "trust me i know what im doing, i know the value is there, the value is not nil" when you run the code. If you're wrong you crash.
Unless you really know what you're doing. Avoid using the "!"
force unwrap operator. Probably the leading cause of crashes for beginning Swift programmers.
Dealing with optionals(The worst way)
Why did I get “Fatal error: Unexpectedly found nil while unwrapping an Optional value”?
You probably did one of the following.
1. Explicit Force Unwrapping
This is done with the ! operator on an optional. For example:
let optionalString: String?
print(optionalString!) // <- CRASH
Fatal error: Unexpectedly found nil while unwrapping an Optional value
As optionalString
is nil
here, you will get a crash on the line where you force unwrap it.
2. Implicitly Unwrapped Optionals
These are defined with a !
, rather than a ?
after the type.
var optionalInt: Int! // this value is implicitly unwrapped wherever it's used
These optionals are assumed to contain a value. Therefore whenever you access an implicitly unwrapped optional, it will automatically be force unwrapped for you. If it doesn’t contain a value, it will crash.
print(optionalInt) // <- CRASH
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
IBOutlets, are often implicitly unwrapped optionals. This is because the xib or storyboard will link up the outlets only at runtime, after initialization. Therefore you should make sure that you're not accessing outlets before the're loaded in memory. Also insure that the connections are correct in your storyboard or xib file, otherwise the values will be nil
at runtime, therefore crash when being used for the first time. If you're attempting to fix this error(connections) try deleting the lines of code that define your outlets, remove the link from the xib or storyboard if it's still there, the reconnect them.
If you want a full guide comment below.
3. Forced (down)casts
let myString = someShape as! String
Here, by force casting you tell the compiler to no longer worry, as you'll always have a String
instance there. And as long as that holds, you don't have to worry. The problems start when you or your code parteners from the project start circulating non-String values. Crashes!!
4. Values coming from Objective-C
Values coming from Objective-C that don't have nullability annotations. Let's assume we have the following Objective-C class:
@interface MyUser: NSObject
@property NSString *name;
@end
Now if no nullability annotations are specified (either explicitly or via NS_ASSUME_NONNULL_BEGIN/NS_ASSUME_NONNULL_END), then the name property will be imported in Swift as String! (an IUO - implicitly unwrapped optional). As soon as some swift code will want to use the value, it will crash if name is nil.
Safely dealing with optionals(The best way)
Solutions? There're many ways of dealing with optionals that are safer.
Swift is a type-safe language, which means the language helps you to be clear about the types of values your code can work with. If part of your code requires a String, type safety prevents you from passing it an Int by mistake. Likewise, type safety prevents you from accidentally passing an optional String to a piece of code that requires a non-optional String. Type safety helps you catch and fix errors as early as possible in the development process.
1. Optional Binding
This allows you to check if an optional contains a value and allows you to assign the unwrapped value to a new variable or constant.
if let number = optionalInt {
print("Contains a value! It is \(number)!")
} else {
print("Doesn’t contain a number")
}
What this does is first check that the optional contains a value. If it does, then the ‘unwrapped’ value is assigned to a new variable (number
) – which you can then freely use as if it were non-optional. If the optional doesn’t contain a value, then the else clause will be invoked, as you would expect.
What’s neat about optional binding, is you can unwrap multiple optionals at the same time. You can just separate the statements with a comma. The statement will succeed if all the optionals were unwrapped.
var optionalInt : Int?
var anOptionalString : String?
if let number = optionalInt, let text = anOptionalString {
print("optionalInt contains a value: \(number). And so does anOptionalString, it’s: \(text)")
} else {
print("One or more of the optionals don’t contain a value")
}
Another neat trick is that you can also use commas to check for a certain condition on the value, after unwrapping it.
if let number = optionalInt, number > 0 {
print("optionalInt contains a value: \(number), and it’s greater than zero!")
}
The only catch with using optional binding within an if statement, is that you can only access the unwrapped value from within the scope of the statement. If you need access to the value from outside of the scope of the statement, you can use a guard statement.
2. Guard Statement
A guard statement allows you to define a condition for success – and the current scope will only continue executing if that condition is met. They are defined with the syntax guard condition else {...}
.
guard let number = optionalInt else {
return
}
Note that within the guard body, you must use one of the control transfer statements in order to exit the scope of the currently executing code.
If optionalInt
contains a value, it will be unwrapped and assigned to the new number
constant. The code after the guard will then continue executing. If it doesn’t contain a value – the guard will execute the code within the brackets, which will lead to transfer of control, so that the code immediately after will not be executed.
The real neat thing about guard statements is the unwrapped value is now available to use in code that follows the statement (as we know that future code can only execute if the optional has a value). This is a great for eliminating ‘pyramids of doom’ created by nesting multiple if statements.
guard let number = optionalInt else {
return
}
print("optionalInt contains a value, and it’s: \(number)!")
Guards also support the same neat tricks that the if statement supported, such as unwrapping multiple optionals at the same time and using the where clause.
Whether you use an if or guard statement completely depends on whether any future code requires the optional to contain a value.
3. Optional Chaining
You can use Optional Chaining in order to call a method or access a property on an optional. This is simply done by suffixing the variable name with a ?
when using it.
For example, say we have a variable foo, of type an optional Foo
instance.
var foo : Foo?
If we wanted to call a method on foo
that doesn’t return anything, we can simply do:
foo?.doSomethingInteresting()
If foo contains a value, this method will be called on it. If it doesn’t, nothing bad will happen – the code will simply continue executing.
This is similar behaviour to sending messages to nil in Objective-C
This can therefore also be used to set properties as well as call methods. For example:
foo?.bar = Bar()
Again, nothing bad will happen here if foo
is nil
. Your code will simply continue executing.
Another neat trick that optional chaining lets you do is check whether setting a property or calling a method was successful. You can do this by comparing the return value to nil
.
This is because an optional value will return
Void?
rather thanVoid
on a method that doesn’t return anything.
Example:
if (foo?.bar = Bar()) != nil {
print("bar was set successfully")
} else {
print("bar wasn’t set successfully")
}
4. Nil Coalescing Operator
The Nil Coalescing Operator is a nifty shorthand version of the ternary conditional operator, primarily designed to convert optionals to non-optionals. It has the syntax a ?? b
, where a
is an optional type and b
is the same type as a
(although usually non-optional).
It essentially lets you say “If a contains a value, unwrap it. If it doesn’t then return b instead”. For example, you could use it like this:
let number = optionalInt ?? 0
This will define a number
constant of Int
type, that will either contain the value of optionalInt
, if it contains a value, or 0
otherwise.
It’s just shorthand for:
let number = optionalInt != nil ? optionalInt! : 0
Bye, C4