Unsafe Unwrapping
In the previous articles we have seen safe and unsafe ways of unwrapping optionals. Using the ! operator on optional variables will result in a crash. This is called forced unwrapping of the optionals. And the implicit unwrapping by adding ! at the end of the Type in the declaration will also result in a crash if the value of the optional is nil.
Both the above situations should be used only where it makes sense. Those previous articles further described what those situations are.
Safe Unwrapping
Now let revisit again the safer ways of unwrapping an optional. And let’s see how it can be made shorter but still safe by using the Nil Coalescing operator.
One way of safe unwrapping is to check whether the optional in question has a value nil.
// city is made optional, because we don’t have a value for this yet.
var city: String?
// A little bit down the road we got the value for city
// Sometimes this might not happen
city = “San Francisco”
// displayString is not optional
// it needs to be set before it is used
var displayCity: String
if city != nil {
displayCity = city!
} else {
displayCity = “Please Set City”
}
print(displayCity)
Then there is the second way — Optional Binding — where you create non-optional variable/constant in the if clause and use it.
// Same logic as above - city is not available right away
var city: String?
city = “San Francisco”
var displayCity: String
// Optional Binding way of safe unwrapping of an optional
if let city = city {
displayCity = city
} else {
displayCity = “Please Set City”
}
Both the above scenarios work. But in both the cases there are 5 lines of code just to add a default string. The patterns above are definitely useful and used all over (especially the optional binding pattern). However, there is a shorter method for situations like this.
Safe Unwrapping: nil coalescing operator
Swift has an operator called Nil Coalescing Operator. It is ?? (two question marks together). It simplifies the way of safely unwrapping:
var city: String?
city = “San Francisco”
var displayCity = city ?? “Please Set City”
What does this phrase mean: city ?? “Please Set City”
The nil coalescing operator (??) above will return city if city is not nil. But if city is nil, then “Please Set City” is returned. This follows the logic in the nil checking code above.
This can be used in situations where you give option to the user to set sizes, colors, greetings, etc. And the app will also have default values for all of them. If the user doesn’t bother provide separate values, you can use the default values with the help of nil coalescing operator very easily.
The ?: operator works in Swift as well:
// Following two are identical
// ?:
displayCity = city != nil ? city! : “Please Set City”
// ??
displayCity = city ?? “Please Set City”
The code in ?: says: if city is not nil, then unwrap city and return it. Otherwise, return the string “Please Set City”. The ?? operator is exactly the same, but uses a shorthand notation.
For the ?? operator to be useful, the first operand (city here) must be an optional. It’s the same in the case of ?: — the variable/constant that is being checked must be an optional. If not, there is no point in checking, it will always be non-nil.
However, the ?? and ?: operators behave slightly differently. As shown in the code below, explicit comparison to nil (of a non-optional) produces error.
// city is a non-optional
var city = "San Francisco"
// Works fine
// ?? just checks whether city is nil or not
var displayCity = city ?? "Please Set City"
// Doesn’t work, because city is never going to be nil
displayCity = city != nil ? city! : "Please Set City"
For Dictionaries and Arrays
The Nil Coalescing Operator can be used in dictionaries — if the key being searched is not there in the dictionary, it will return nil. So with ??, you can return some other default value.
var airports = ["SFO": "San Francisco", "NYC": "New York”]
// A Dictionary of key(airport code): value(city name) codes
var city = airports["ORD"] ?? "No City"
// Since there is no key for ORD in the dictionary,
// city will now have the string “No City”, instead of nil
[END CODE
If the array index being searched is over the maximum, array wouldn’t return a nil. It crashes. So, ?? will not be of much use in this case — it will still crash. Whether the index is within range check needs to be made here.
[CODE]
var airports = [“SFO”, “NYC”]
var airport = airports[3] ?? “SFO”
// Crashes with fatal error: Index out of range.
// The ?? will not make a difference here