The Swift Programming Language guide has the following example:
class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
deinit { println("\(name) is being deinitialized") }
}
class Apartment {
let number: Int
init(number: Int) { self.number = number }
var tenant: Person?
deinit { println("Apartment #\(number) is being deinitialized") }
}
var john: Person?
var number73: Apartment?
john = Person(name: "John Appleseed")
number73 = Apartment(number: 73)
//From Apple's “The Swift Programming Language” guide (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html)
Then when assigning the apartment to the person, they use an exclamation point to "unwrap the instance":
john!.apartment = number73
What does it mean to "unwrap the instance"? Why is it necessary? How is it different from just doing the following:
john.apartment = number73
I'm very new to the Swift language. Just trying to get the basics down.
UPDATE:
The big piece of the puzzle that I was missing (not directly stated in the answers - at least not at the time of writing this) is that when you do the following:
var john: Person?
that does NOT mean that "john
is of type Person
and it might be nil", as I originally thought. I was simply misunderstanding that Person
and Person?
are completely separate types. Once I grasped that, all of the other ?
, !
madness, and the great answers below, made a lot more sense.
TL;DR
What does an exclamation mark mean in the Swift language?
Example
Source: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_399
john
is an optionalvar
. So can be contains anil
value. To ensure that the value isn't nil use a!
at the end of thevar
name.From documentation
“Once you’re sure that the optional does contain a value, you can access its underlying value by adding an exclamation mark (!) to the end of the optional’s name. The exclamation mark effectively says, “I know that this optional definitely has a value; please use it.”
Another way to check non nil value is
If you've come from a C-family language, you will be thinking "pointer to object of type X which might be the memory address 0 (NULL)", and if you're coming from a dynamically typed language you'll be thinking "Object which is probably of type X but might be of type undefined". Neither of these is actually correct, although in a roundabout way the first one is close.
The way you should be thinking of it is as if it's an object like:
When you're testing your optional value with
foo == nil
it's really returningfoo.isNil
, and when you sayfoo!
it's returningfoo.realObject
with an assertion thatfoo.isNil == false
. It's important to note this because iffoo
actually is nil when you dofoo!
, that's a runtime error, so typically you'd want to use a conditional let instead unless you are very sure that the value will not be nil. This kind of trickery means that the language can be strongly typed without forcing you to test if values are nil everywhere.In practice, it doesn't truly behave like that because the work is done by the compiler. At a high level there is a type
Foo?
which is separate toFoo
, and that prevents funcs which accept typeFoo
from receiving a nil value, but at a low level an optional value isn't a true object because it has no properties or methods; it's likely that in fact it is a pointer which may by NULL(0) with the appropriate test when force-unwrapping.There other situation in which you'd see an exclamation mark is on a type, as in:
This is roughly equivalent to accepting an optional with a forced unwrap, i.e.:
You can use this to have a method which technically accepts an optional value but will have a runtime error if it is nil. In the current version of Swift this apparently bypasses the is-not-nil assertion so you'll have a low-level error instead. Generally not a good idea, but it can be useful when converting code from another language.
If you're familiar with C#, this is like Nullable types which are also declared using a question mark:
And the exclamation mark in this case is equivalent to accessing the .Value property of the nullable type like this:
In this case...
var John: Person!
it means, that initially John will have nil value, it will be set and once set will never be nil-led again. Therefore for convenience I can use the easier syntax for accessing an optional var because this is an "Implicitly unwrapped optional"