1

Why does this piece of code give me an Fatal Error

var number: Int? = .none
print(number!)

Fatal error: Unexpectedly found nil while unwrapping an Optional value

But this piece of code does not?

var number: Int! = .none
print(number)

nil

Doesn't Int! automatically unwrap the variable on use? Why doesn't it throw a fatal error when number gets printed?

  • 1
    Compare https://stackoverflow.com/q/39633481/1187415 or https://stackoverflow.com/q/39537177/1187415: An IUO is treated as a regular optional whenever possible, and only unwrapped if needed. – Martin R Feb 20 '18 at 23:21
  • Well it did used to get implicitly unwrapped when being coerced to `Any`, but now the behaviour is only to implicitly unwrap when the value *has to* be treated as the non-optional type (I need to update [my answer here for that](https://stackoverflow.com/questions/39537177/swift-3-incorrect-string-interpolation-with-implicitly-unwrapped-optionals/39537558#39537558)). Basically IUOs are wacky things, you should avoid them in most cases. – Hamish Feb 20 '18 at 23:21
  • Worth noting btw that the compiler should warn on the implicit coercion from an IUO to Any; that got fixed in https://github.com/apple/swift/pull/14221 – Hamish Feb 20 '18 at 23:41

2 Answers2

0

An Optional is a type that can hold or not a wrapped value.

In the first case, you're telling inside the code that numbers contains an Int variable (this is because of numbers!), which is a very unsafe way to work with Optionals. When you unwrap numbers, it has to contain a value or, on the contrary, has to not be nil. Since the compiler actually finds that there isn't an Int value but nil, so it calls fatal error.

In the second case, instead, you're simply printing an Optional, that can hold or not an Int value. In this specific case, it does not hold an Int value, so nil will be printed.

Here you can find more on Optionals: https://developer.apple.com/documentation/swift/optional

  • But in the second case: Shouldn’t be “Optional(nil)” printed if it’s printing an optional? –  Feb 21 '18 at 00:01
  • @Manuel it only does that for non-nil values. Also keep in mind that `print` coerces values to `Any`, which changes how it gets displayed. But you can see it with string interpolation: `print("\(0 as Int!)")` prints `Optional(0)` (but `print("\(nil as Int!)")` just prints nil). – John Montgomery Feb 21 '18 at 00:16
0

Implicitly unwrapped optionals are still optionals under the hood; they just get automatically unwrapped as needed.

However, the print function accepts optional values, so unwrapping it there isn't needed. In the first case you get an error because you're explicitly unwrapping it, but in the second it's happy to keep it wrapped so there's no error. It'll work like that with other functions that accept optionals as well, but if you use it somewhere that an optional does not work, then it forces an unwrap and the behavior becomes the same for both:

let num1: Int! = nil
let num2: Int? = nil

print(String(describing: num1)) // works fine
print(String(describing: num2!)) // error

print(num1 + 1) // error
print(num2! + 1) // also error
John Montgomery
  • 6,739
  • 9
  • 52
  • 68