mitrenegade
mitrenegade

Reputation: 1844

Swift optionals behavior in if statement

I have a if statement that tries to compare an existing type (String) of a room, that could be nil, to a list of room types for a UIPicker. If the room name doesn't exist, we set the picker automatically to "Other".

However, i'm unable to get into the else if statement even though the conditions are met (room is nonnil, type is nil, and for some value of i, string is "Other"). The desired behavior is to set the pickerTypes row to the index for "Other". However, we seem to skip over the else if statement and never go in. Anyone have any insight on optionals or if statements for why?

    for var i=0; i<roomTypesCount; i++ {
        let string = getName(i)
        if string == self.room?.type {
            self.pickerTypes.selectRow(i, inComponent: 0, animated: false)
        }
        else if self.room?.type == nil && string == "Other" {
            self.pickerTypes.selectRow(i, inComponent: 0, animated: false)
        }
    }

getName() is an objective c method that returns an NSString. Room is a core data object which is nonnil at this time, but its type is nil.

This doesn't ever go into the if statement: else if self.room?.type == nil && string == "Other" { This does. else if self.room!.type == nil && string == "Other" { So does this else if self.room?.type == nil && true {

In the debug console, we get some interesting behavior:

(lldb) po self.room?.type 
nil

(lldb) po self.room!.type 
fatal error: unexpectedly found nil while unwrapping an Optional value
fatal error: unexpectedly found nil while unwrapping an Optional value 
nil

Other evaluations of the logic:

(lldb) po string == "Other"
true

(lldb) po self.room?.type == nil
true

(lldb) po self.room?.type == nil && string == "Other"
false

(lldb) po (self.room?.type == nil && string == "Other")
false

(lldb) po (self.room?.type == nil) && (string == "Other")
false

Finally, if we just declare string as a type String, it works:

        let string: String = getName(i)

In the console:

(lldb) po self.room?.type == nil && string == "Other"
true

Any ideas? To help me improve my understanding of optionals.

Upvotes: 1

Views: 78

Answers (1)

Allanah Fowler
Allanah Fowler

Reputation: 1281

When you try to access a property of an optional, you first need to check that the optional value exists. Since self.room is an optional, you need to check that it exists before trying to access type.

if let room = self.room {
    print("room is not nil")
    if let type = room.type {
        print("type is not nil")
    } else if string == "Other" {
        print("type is nil and string is Other")
    } else {
        print("type is nil but string is \(string)")
    }
} else if string == "Other" {
    print("room is nil and string is Other")
} else {
    print("room is nil but string is \(string)")
}

Upvotes: 2

Related Questions