unexpectedly found nil while unwrapping an optional value – Code Example

Total
0
Shares

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)
}

Live Demo

Open Live Demo