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.
An implicitly unwrapped optional is defined with an exclamation mark instead of a question mark. The exclamation mark indicates that the name property of the Person class is defined as an implicitly unwrapped optional. Note that the print statement returns the value of name , not an optional.
Some programming and scripting languages also use exclamation points to indicate warnings and errors, as well as a method to identify a non-executable line of the code/statement. In UNIX scripting, the exclamation point is used for telling the operating system which application to use for running the script.
Punctuation Marks Are Writing Conventions Exclamation marks make a sentence more exciting, emphatic or emotional. They serve a specific purpose when setting a sentence's tone.
It is used to end a rhetorical question or a simultaneous question and exclamation. Some writers, then, began using multiple exclamation points as a logical outgrowth of the interbang and single exclamation mark to add even more emphasis to words, phrases, and sentences.
What does it mean to "unwrap the instance"? Why is it necessary?
As far as I can work out (this is very new to me, too)...
The term "wrapped" implies we should think of an Optional variable as a present, wrapped in shiny paper, which might (sadly!) be empty.
When "wrapped", the value of an Optional variable is an enum with two possible values (a little like a Boolean). This enum describes whether the variable holds a value (Some(T)
), or not (None
).
If there is a value, this can be obtained by "unwrapping" the variable (obtaining the T
from Some(T)
).
How is
john!.apartment = number73
different fromjohn.apartment = number73
? (Paraphrased)
If you write the name of an Optional variable (eg text john
, without the !
), this refers to the "wrapped" enum (Some/None), not the value itself (T). So john
isn't an instance of Person
, and it doesn't have an apartment
member:
john.apartment // 'Person?' does not have a member named 'apartment'
The actual Person
value can be unwrapped in various ways:
john!
(gives the Person
value if it exists, runtime error if it is nil)if let p = john { println(p) }
(executes the println
if the value exists)john?.learnAboutSwift()
(executes this made-up method if the value exists)I guess you choose one of these ways to unwrap, depending upon what should happen in the nil case, and how likely that is. This language design forces the nil case to be handled explicitly, which I suppose improves safety over Obj-C (where it is easy to forget to handle the nil case).
Update:
The exclamation mark is also used in the syntax for declaring "Implicitly Unwrapped Optionals".
In the examples so far, the john
variable has been declared as var john:Person?
, and it is an Optional. If you want the actual value of that variable, you must unwrap it, using one of the three methods above.
If it were declared as var john:Person!
instead, the variable would be an Implicitly Unwrapped Optional (see the section with this heading in Apple's book). There is no need to unwrap this kind of variable when accessing the value, and john
can be used without additional syntax. But Apple's book says:
Implicitly unwrapped optionals should not be used when there is a possibility of a variable becoming nil at a later point. Always use a normal optional type if you need to check for a nil value during the lifetime of a variable.
Update 2:
The article "Interesting Swift Features" by Mike Ash gives some motivation for optional types. I think it is great, clear writing.
Update 3:
Another useful article about the implicitly unwrapped optional use for the exclamation mark: "Swift and the Last Mile" by Chris Adamson. The article explains that this is a pragmatic measure by Apple used to declare the types used by their Objective-C frameworks which might contain nil. Declaring a type as optional (using ?
) or implicitly unwrapped (using !
) is "a tradeoff between safety and convenience". In the examples given in the article, Apple have chosen to declare the types as implicitly unwrapped, making the calling code more convenient, but less safe.
Perhaps Apple might comb through their frameworks in the future, removing the uncertainty of implicitly unwrapped ("probably never nil") parameters and replacing them with optional ("certainly could be nil in particular [hopefully, documented!] circumstances") or standard non-optional ("is never nil") declarations, based on the exact behaviour of their Objective-C code.
Here is what I think is the difference:
var john: Person?
Means john can be nil
john?.apartment = number73
The compiler will interpret this line as:
if john != nil { john.apartment = number73 }
While
john!.apartment = number73
The compiler will interpret this line as simply:
john.apartment = number73
Hence, using !
will unwrap the if statement, and make it run faster, but if john is nil, then a runtime error will happen.
So wrap here doesn't mean it is memory wrapped, but it means it is code wrapped, in this case it is wrapped with an if statement, and because Apple pay close attention to performance in runtime, they want to give you a way to make your app run with the best possible performance.
Update:
Getting back to this answer after 4 years, as I got the highest reputations from it in Stackoverflow :) I misunderstood a little the meaning of unwrapping at that time. Now after 4 years I believe the meaning of unwrapping here is to expand the code from its original compact form. Also it means removing the vagueness around that object, as we are not sure by definition if it is nil or not. Just like the answer of Ashley above, think about it as a present which could contain nothing in it. But I still think that the unwrapping is code unwrapping and not memory based unwrapping as using enum.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With