topic{Swouston, we’ve had a problem. Optionals and bools.}

I'm leaving here this ugly article as a reminder, that I need to maintain this place.

Swift is a very interesting and promising new language. Tons of great built-in fascinating features are going to rock (when they start working=) ). But today I’d like to take a break and describe one little subclass of errors which can confuse everybody from beginners to Objective-C professionals. So, what could be wrong with this code?

boolValue = false
if (boolValue)
{
    NSLog("bool value is true! yeah!")
}

For experienced ones or at least those who have read the Swift book it’s obvious that this condition can NOT be evaluated to false and there could be new entry in the log.

But, why or when?

Yeah, optionals. If boolValue is an optional (one declared with ? after type specifier) the condition above evaluates to false and there’ll be no message in the log. Again, if

var boolOptional:Bool?

and then:

boolOptional = false
if (boolOptional) // wrapped
{
    NSLog("true! yeah!")
}
else
{
    NSLog("false.")
}

there’ll be “true! yeah!” in the log!
That’s because boolOptional is an optional Bool. You can imagine an optional as a separate type (which it, probably, is) like this:

Type Optional  {
    BOOL hasValue
    Type value

    func unwrapValueOrCrash() -> Type {
        if (hasValue == false)
        {
            CRASH() // crash your app hard
        }
        return value
    }
}

When an optional is used in a condition like if-else it could be used as:

  1. Wrapped, value container, i.e. if it has value it evaluates to true, if not, it evaluates to false. You just type variable name without exclamation mark like this: boolOptional.

    Using the abstraction above assume:

    if ( optional ) == if ( optional.hasValue )
    

    var boolOptional:Bool? = false
    if ( boolOptional ) // wrapped, no !
    {
        NSLog("true! yeah!") // boolOptional has a value (false), so execution goes here
    }
    else
    {
        NSLog("false.") // boolOptional has a value and it is false, but we're checking if it has value or not at all
    }
    
  2. Unwrapped, value, i.e. you use it’s value, if the value is true it evaluates to true, if the value is false it evaluates to false. You type an exclamation mark after variable name like this: boolOptional!. But note, if you unwrap optional without value your app will crash.

    Using the abstraction above assume:

    if ( optional! ) == if ( optional.unwrapValueOrCrash() )
    

    var boolOptional:Bool? = false
    if ( boolOptional! ) // unwrapping, has !
    {
        NSLog("true! yeah!") // boolOptional has a value and it is false
    }
    else
    {
        NSLog("false.") // as expected, we're checking the value and it is false
    }
    ...
    boolOptional = nil // assign no value
    if ( boolOptional! ) // crash, you're unwrapping optional without a value, you should always make sure if it has a value before unwrapping
    

Also note, that for if statement in Swift ( braces ) around condition are not compulsory, you are free to write

if condition
{}

or

if (condition)
{}

they are effectively the same. You only must include { curly braces }, so no one-line-ifs anymore (and I personally love this, I hate when people use them).

Now it’s clear, that optionals, especially Bool optionals should be used with care, I’d even suggest avoiding using optional Bools as it could cause such subtle bugs.

К списку постов   На главную
comments
Комментарии закрыты.