I'm learning Swift for iOS 8 / OSX 10.10 by following this tutorial, and the term "unwrapped value" is used several times, as in this paragraph (under Objects and Class):
When working with optional values, you can write ? before operations like methods, properties, and subscripting. If the value before the ? is nil, everything after the ? is ignored and the value of the whole expression is nil. Otherwise, the optional value is unwrapped, and everything after the ? acts on the unwrapped value. In both cases, the value of the whole expression is an optional value.
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength
I don't get it, and searched on the web without luck.
What does this means?
From Cezary's answer, there's a slight difference between the output of the original code and the final solution (tested on playground) :
The superclass' properties are shown in the output in the second case, while there's an empty object in the first case.
Isn't the result supposed to be identical in both case?
Related Q&A : What is an optional value in Swift?
First, you have to understand what an Optional type is. An optional type basically means that the variable can be nil
.
Example:
var canBeNil : Int? = 4
canBeNil = nil
The question mark indicates the fact that canBeNil
can be nil
.
This would not work:
var cantBeNil : Int = 4
cantBeNil = nil // can't do this
To get the value from your variable if it is optional, you have to unwrap it. This just means putting an exclamation point at the end.
var canBeNil : Int? = 4
println(canBeNil!)
Your code should look like this:
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare!.sideLength
A sidenote:
You can also declare optionals to automatically unwrap by using an exclamation mark instead of a question mark.
Example:
var canBeNil : Int! = 4
print(canBeNil) // no unwrapping needed
So an alternative way to fix your code is:
let optionalSquare: Square! = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare.sideLength
The difference that you're seeing is exactly the symptom of the fact that the optional value is wrapped. There is another layer on top of it. The unwrapped version just shows the straight object because it is, well, unwrapped.
A quick playground comparison:
In the first and second cases, the object is not being automatically unwrapped, so you see two "layers" ({{...}}
), whereas in the third case, you see only one layer ({...}
) because the object is being automatically unwrapped.
The difference between the first case and the second two cases is that the second two cases will give you a runtime error if optionalSquare
is set to nil
. Using the syntax in the first case, you can do something like this:
if let sideLength = optionalSquare?.sideLength {
println("sideLength is not nil")
} else {
println("sidelength is nil")
}