Checking for nil
In the previous articles we discussed how to unwrap an optional to get the value inside. These methods including forced unwrapping that uses ! on the variable and implicit unwrapping that uses the ! on the type in the declaration statement. Both of these methods are unsafe because if they encounter nil (i.e. no-value) during unwrapping the program will crash.
Now let’s see how to unwrap an optional safely. One of the ways is to explicitly test for nil. And we can unwrap the variable only if the optional is not nil. Otherwise we will not unwrap the optional and find some other way to address the situation.
// city is an Optional String
var city: String?
// Somewhere down in the code, after results are obtained from the Internet
city = “San Francisco”
var displayString = “How are you in “
// Test city for nil
if city != nil {
// Now city can be force unwrapped without any problem
displayString += city! + “?”
} else {
displayString = “How are you today?”
}
print(displayString)
In the above code if the city optional has not been set by the time displayString needs it, the nil test would have been failed and the execution will go into the else clause. Overall, the code will run properly whether city is set or not. The displayString variable would have been set correctly according to each situation.
Optional Binding
In the above code, we are still doing the forced unwrapping by using city! in the if clause. And this explicit check for nil is not very elegant. Now a better way of safely unwrapping the optional in Swift - called Optional Binding.
// Just like before city is Optional String
// And it might or might not be set to a proper String down the road
var city: String?
city = “San Francisco”
var displayString = “How are you in “
if let tempCity = city {
// Execution will come here only if tempCity is not nil.
// There is no need to unwrap that variable.
displayString += tempCity + “?”
} else {
displayString = “How are you today?”
}
print(displayString)
The key line for Optional Binding in the above code is this:
We are creating a constant (let) variable of the same type wrapped inside the optional of the variable we are trying to unwrap. And that variable tempCity is of type String - if you look at the Help on tempCity in Playgrounds (by doing Option-Click on tempCity), you will see the following:
Typically, you want this to be declared constant (by using let). However, if there is a need, you can also make it a var. In either case, this constant/variable will only be available inside the if-block.
Part of above code can also be written with var:
…
if var tempCity = city {
tempCity += “?”
displayString += tempCity
} else {
…
In the above code tempCity was made var and some additional changes have been made to it, which would not have been possible if it was declared a constant (let).
Preferred Way
In the above code, the name “tempCity” is used in the optional binding. Preferred way is to use the same optional variable name itself - which would be “city” in this case.
var city: String?
city = “San Francisco”
var displayString = “How are you in “
if let city = city {
displayString += city + “?”
} else {
displayString = “How are you today?”
}
print(displayString)
As you can see above city is used twice in optional binding: if let city = city … This is perfectly valid and actually the suggested/preferred way of naming this constant. In this case, the city constant declared in the if clause will be non-optional String in the if block. The outside city with type String? will be available as Optional String elsewhere.
So, for Optional Binding, following are the points:
- The newly created constant will only be available in the if-block
- It will NOT be available in the else-block
- It will NOT be available below if-else block
- If the optional has a non-nil value, if block will be executed
- Type of optional bound constant/variable is same as the Wrapped type - non-optional
- If the optional has a nil value, the else block will be executed
- While making this a var also works, normally you want it to be let
- Preferred way is to name both the optional and non-optional same