112

I understand that in Swift all variables must be set with a value, and that by using optionals we can set a variable to be set to nil initially.

What I don't understand is, what setting a variable with a ! is doing, because I was under the impression that this "unwraps" a value from an optional. I thought by doing so, you are guaranteeing that there is a value to unwrap in that variable, which is why on IBActions and such you see it used.

So simply put, what is the variable being initialized to when you do something like this:

var aShape : CAShapeLayer!

And why/when would I do this?

Luca Angeletti
  • 58,465
  • 13
  • 121
  • 148
Jason Renaldo
  • 2,802
  • 3
  • 37
  • 48
  • You would do this to tell that a variable is nt nil **after** you checked this fact. – Matthias Jun 09 '14 at 14:40
  • I don't think this should be marked as a duplicate. "What is an optional?" is not the same question as "What is the difference between the two types of optionals?" which is pretty much what *this* question is – Jiaaro Jun 18 '14 at 14:30
  • @Jiaaro even in that case, there are already tons of questions regarding optionals, implicitly unwrapped optionals, and the like. You can also refer to this one: http://stackoverflow.com/questions/24272781/in-apple-swift-in-what-cases-would-i-not-want-an-implicitly-unwrapped-optiona – Jack Jun 18 '14 at 15:04
  • @JackWu Ok, but I'm pretty sure this question wasn't a duplicate when it was asked. (it was asked a full week before your example, for instance) – Jiaaro Jun 18 '14 at 15:39
  • @Jiaaro You make a good point, I didn't notice this was older..maybe that other one should be marked as a duplicate of this one instead.. – Jack Jun 18 '14 at 15:42

1 Answers1

149

In a type declaration the ! is similar to the ?. Both are an optional, but the ! is an "implicitly unwrapped" optional, meaning that you do not have to unwrap it to access the value (but it can still be nil).

This is basically the behavior we already had in objective-c. A value can be nil, and you have to check for it, but you can also just access the value directly as if it wasn't an optional (with the important difference that if you don't check for nil you'll get a runtime error)

// Cannot be nil
var x: Int = 1

// The type here is not "Int", it's "Optional Int"
var y: Int? = 2

// The type here is "Implicitly Unwrapped Optional Int"
var z: Int! = 3

Usage:

// you can add x and z
x + z == 4

// ...but not x and y, because y needs to be unwrapped
x + y // error

// to add x and y you need to do:
x + y!

// but you *should* do this:
if let y_val = y {
    x + y_val
}
Jiaaro
  • 74,485
  • 42
  • 169
  • 190
  • 7
    Implicitly unwrapped optionals are described in an aptly named section starting on page 56 of *The Swift Programming Language*. – Caleb Jun 09 '14 at 14:46
  • @Caleb I've added a link to the relevant section of the online docs where I mentioned implicitly unwrapped optionals :) – Jiaaro Jun 09 '14 at 14:51
  • Great information, thanks. Generally loving the safety that Swift is forcing on us so far, should produce a lot less bugs :). – Jason Renaldo Jun 09 '14 at 14:52
  • @Jiaaro: Thank you so much for sharing. It makes user to understand Perfectly by above example.!! :) – Esha Dec 06 '14 at 07:19
  • 4
    I think the sentence "*This is basically the behavior we already had in objective-c*" can be confusing. In objective-c one can access a `nil` value and actually "work" with it, in swift accessing an implicitly unwrapped optional while it's nil __will__ throw a runtime exception. – Sascha Wolf Jun 06 '16 at 11:17
  • @Jiaaro, **If I am correct**, the line of code `if let y_val = y` tells that declare constant variable with name `y_val` which is "Implicitly Unwrapped Optional" type, then take optional value of `y` unwrap it and assign to `y_val`. Please let me know my assumption is correct or any thing I missed. BTW Thanks for simplified explanation. – Nasir Nov 03 '16 at 06:59
  • But why array can be nil without using "?" and "!" marks? For example: `var mutableArray: [Int] = [Int]()` and then `print("\(mutableArray.first)")` display nil. – Piotr Wasilewicz Jan 17 '17 at 10:49
  • @PiotrWasilewicz array.first is a getter that returns an optional (because an array can have zero items) – Jiaaro Jan 17 '17 at 14:38
  • Thanks for this clarification Jiaaro! – Chris8447 Jul 14 '19 at 16:10