Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The implicit unwrapping of an optional boolean

Tags:

swift

The implicit unwrapping of a Bool type does not seem to work:

var aBoolean: Bool!    // nil
aBoolean = false       // false
aBoolean               // false

aBoolean == true       // false
aBoolean == false      // true

if aBoolean {
    "Hum..."            // "Hum..."
} else {
    "Normal"
}

if aBoolean! {
    "Hum..."
} else {
    "Normal"          // "Normal"
}

If I had declared aBoolean like var aBoolean: Bool?, this would have been the expected behavior but here, I don't get it.

Is this the correct behavior? I didn't find any doc about it.

Thanks!

like image 614
Damien Avatar asked Jun 09 '14 20:06

Damien


People also ask

What is implicit unwrapping?

Checking an optionals value is called “unwrapping”, because we're looking inside the optional box to see what it contains. Implicitly unwrapping that optional means that it's still optional and might be nil, but Swift eliminates the need for unwrapping.

How do you unwrap optional binding?

An if statement is the most common way to unwrap optionals through optional binding. We can do this by using the let keyword immediately after the if keyword, and following that with the name of the constant to which we want to assign the wrapped value extracted from the optional.

What is the difference between unwrapping an optional with with and with implicit unwrapping?

The only difference between them is that implicitly unwrapped optionals are a promise to the swift compiler that it's value will NOT be nil when accessed at runtime.

Why use implicitly unwrapped optionals?

Implicitly unwrapped optionals are a compromise between safety and convenience. If you declare a property as optional, then you need to use optional binding or optional chaining every time you access the value of the optional.


4 Answers

The first test is checking whether aBoolean stores a value rather than nil, which it does:

if aBoolean {
    "Hum..."            // "Hum..."
else {
    "Normal"
}

The second test is checking against the actual boolean value stored in aBoolean, which is false:

if aBoolean! {
    "Hum..."
} else {
    "Normal"          // "Normal"
}

This is Illustrated in the Swift book in the "Implicitly Wrapped Optionals" section. I think the implicit unwrapping just doesn't apply with if-statements. I agree it is strange but here is the Apple example:

You can still treat an implicitly unwrapped optional like a normal optional, to check if it contains a value:

let assumedString: String! = "An implicitly unwrapped optional string."

if assumedString {
    println(assumedString)
}
// prints "An implicitly unwrapped optional string."

Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/us/jEUH0.l

like image 139
Dash Avatar answered Oct 19 '22 00:10

Dash


Not an answer, but if this is indeed the intended behavior with implicitly unwrapped booleans it's rather disturbing. As soon as you use the expression in any logic proposition it will get unwrapped:

var aBoolean: Bool! = false

if !aBoolean {
    "I'm unwrapping"            // "I'm unwrapping"
}

if aBoolean == false {
    "I'm unwrapping"            // "I'm unwrapping"
}

Say you have this in your code an at some point your model changes and the condition is reversed, you delete the NOT.

if aBoolean {
    "I'm unwrapping"            // <- ouch
}

You just got screwed. Makes me want to avoid the implicit unwrapping.

like image 22
Fernando Mazzon Avatar answered Oct 19 '22 01:10

Fernando Mazzon


You are making two different truth-checks.

Given:

var aBoolean: Bool!    // nil
aBoolean = false       // false

if aBoolean {
    "Hum..."            // "Hum..."
else {
    "Normal"
}

if aBoolean! {
    "Hum..."
} else {
    "Normal"          // "Normal"
}

...in the first if aBoolean, the value is not being unwrapped, it is simply testing the optional type to determine if it stores a value.

In the second if aBoolean!, you are testing the truth-value of the unwrapped Bool.

To see that it is indeed being implicitly-unwrapped (when not used in a conditional), try:

println("value of implicitly-unwrapped aBoolean: \(aBoolean)")

...this will print 'true' when aBoolean is set to true, 'false' when it is set to false, and 'nil' when it has not yet been assigned.

like image 44
fqdn Avatar answered Oct 19 '22 01:10

fqdn


Here is the behavior clearly shown:

> var bool1 : Bool!
bool1: Bool! = nil
> bool1 = false
> (bool1 ? "yes" : "no")
$R19: (String) = "yes"

In the above, since bool1 is an optional (which becomes a Some instance), the conditional of simply bool1 evaluates to true (it is not nil).

> var bool2 : Bool = false
bool2: Bool = false
> (bool2 ? "yes" : "no")
$R25: (String) = "no"

When bool2 is not an optional, the conditional of simply bool2 evaluates to false (the value of bool2)

like image 27
GoZoner Avatar answered Oct 19 '22 02:10

GoZoner