Swift throws thread 1: fatal error: unexpectedly found nil while unwrapping an optional value when you try to unwrap an optional value which has no assigned value.
An optional value is a type which can hold a value or nil. This is a special value which is used to delay the assignment and keeping nil till then.
Code Example
1. Explicit Forced Unwrapping
Forced unwrapping is done using !
operator.
Error Code
let str: String? print(str!)
Here str
is nil. Forced unwrapping will throw fatal error. Output –
Fatal error: Unexpectedly found nil while unwrapping an Optional value
You may also get the error in this form –
jdoodle.swift:2:7: error: constant 'str' used before being initialized print(str!) ^ jdoodle.swift:1:5: note: constant defined here let str: String?
Correct Code
let str: String? = "Swift String" print(str!)
Output –
Swift String
2. Implicit Unwrapping
This type of variables are already defined using !
. When you use these variables, they expect to have values in them.
Error Code
let str: String! print(str)
When you run this, you will get a number of errors, each pointing towards its solution –
jdoodle.swift:5:7: warning: coercion of implicitly unwrappable value of type 'String?' to 'Any' does not unwrap optional print(implicit_str) ^~~~~~~~~~~~ jdoodle.swift:4:5: note: implicitly unwrapped let 'implicit_str' declared here let implicit_str: String! ^ jdoodle.swift:5:7: note: provide a default value to avoid this warning print(implicit_str) ^~~~~~~~~~~~ ?? <#default value#> jdoodle.swift:5:7: note: force-unwrap the value to avoid this warning print(implicit_str) ^~~~~~~~~~~~ ! jdoodle.swift:5:7: note: explicitly cast to 'Any' with 'as Any' to silence this warning print(implicit_str) ^~~~~~~~~~~~ as Any jdoodle.swift:5:7: error: constant 'implicit_str' used before being initialized print(implicit_str) ^ jdoodle.swift:4:5: note: constant defined here let implicit_str: String! ^
Correct Code
let implicit_str: String! = "Another Swift String" print(implicit_str as Any)
Output –
Optional("Another Swift String")
Solutions
1. Check for nil values
let str: String? if str != nil { print(str!) } else { print("str value is nil") }
Output:
str value is nil
2. Binding in variable and checking nil using if-else
let str: String? if let myStr = str { print("str value is \(myStr)") } else { print("str is nil") }
Output:
str is nil
There is a caveat with this approach. The value of myStr
is only available within scope of if
condition.
You can use multiple optional in if
statement. It will only run when all optional have values.
let str: String? let num: Int? if let myStr = str, let number = num { print("str value is \(myStr). num value is \(num)") } else { print("str or num or both are nil") }
3. Using guard to prevent or continue the further code
You can use guard
to prevent further code processing in a function if optional is not valid or nil
. This is useful because it allows you to use optional value outside the scope of guard
; which was not possible with if
condition.
let str: String? guard let myStr = str else { return } // myStr available outside let copyOfMyStr = myStr
4. Using ??
Ternary operator
Use ??
to check the condition as well as pass the default value.
let str: String? print(str ?? "str is nil")
Output:
str is nil
You can also use expanded form of ternary operator ?:
–
let str: String? print(str != nil ? str! : "str is nil")
Output:
str is nil
5. Using do-try-catch
do { let result = try someThrowingFunc() } catch { print(error) }