The Swift Programming Language guide has the following example:
class Person {
let name: String
init(name: String) { self.name = name }
var apar
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:
struct Optional {
var isNil:Boolean
var realObject:T
}
When you're testing your optional value with foo == nil
it's really returning foo.isNil
, and when you say foo!
it's returning foo.realObject
with an assertion that foo.isNil == false
. It's important to note this because if foo
actually is nil when you do foo!
, 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 to Foo
, and that prevents funcs which accept type Foo
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:
func foo(bar: String!) {
print(bar)
}
This is roughly equivalent to accepting an optional with a forced unwrap, i.e.:
func foo(bar: String?) {
print(bar!)
}
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.