Summary of Optionals Operators
Both ? and ! can be used with Type and variable/constant — so that gives us 4 possibilities. ?? is used between variables. Following is a quick summary of three operators used in the context of optionals in Swift:
- ? with Type: variable is an optional, can take nil value
- ? with variable/constant: Optional Chaining
- ! with Type: Implicit Unwrapping
- ! with variable/constant: Forced Unwrapping
- ?? between variables: Nil Coalescing Operator
Sections below provide quick summary of these operators. Previous articles in this series has went into this in a lot more detail.
? with Type - Optional
Using ? with Type is essence of declaring an Optional.
var city: String?
// Can contain a String value
city = “San Francisco”
// Can contain a nil value
city = nil
As the code above shows a type of String? means Optional<String> - it can contain a String value or a no-value (nil).
? with variable/constant - Optional Chaining
To safely get the value of an entire chain where some of the values are optional and might contain a no-value(nil), you would use ? with the optional variable.
let count = cities[“SF”]?.nickname?.characters.count
In the above code, cities is a dictionary. When you get a value out of dictionary, it will return an optional (for the possibility of not finding the key used. So, if the city you are looking for is not there in the dictionary, it will return nil. And since ? (for optional chaining) is used, rest of the expression will not be evaluated and nil will be returned as a value for count.
Similarly, nickname is an optional property. It can have a nil value. To not execute rest of the statement and return a nil value the ? is used next to nickname.
This optional chaining (?) can be used on methods and subscripts in the chain if they return optionals.
! with Type: Implicit Unwrapping
You can use ! on the type to return unwrapped value to the caller. This is used infrequently in the regular code, but used when UI controls are declared in the code and connected with the controls in the storyboard.
@IBOutlet var saveButton: UIButton!
In this case saveButton cannot initialized to a proper UIButton object at the time of creation. But once the button object created in the storyboard is ready, it can be assigned to this. Until then it will be have be nil (or have no-value). But wherever you are using it, it must be ready there — there is no point in using nil user interface objects. So, saveButton will need to be unwrapped and returned to the using place automatically.
This pattern can be used in situations where a value for some variable is nil at some point, but will be obtained from somewhere and when it’s time for using it, it cannot be nil.
! with variable/constant - Forced Unwrapping
If you have declared a variable as an optional and you want to get the value inside it, then you can use ! to force unwrap it.
var city: String?
city = “San Francisco”
var display = “City is “ + city!
If there is no value (nil) in the optional you are trying to unwrap forcibly with !, then there will be a crash. So, this needs to be used only if you are very sure that there is a non-nil value in the optional that you are trying to unwrap.
Safer ways of unwrapping include explicitly checking for nil, optional binding, nil coalescing operator, and optional chaining.
You can also use this to forcibly unwrap at the places where optional is returned, including dictionaries, methods that return an optional, subscripts that return an optional, etc.
?? between variables - Nil Coalescing Operator
A quick way of returning a default value when the original optional has no-value (nil) in it is by using the Nil Coalescing Operator (??)
let defaultLinesToShow = 4
var userLinesToShow: Int?
let linesToShow = userLinesToShow ?? defaultLinesToShow
By default, in our app, we show 4 lines (lets say). However, we also give the user to change it (perhaps 3 or 6). So, the number of lines show will be set to whatever the user sets it to be. However, if the user doesn’t bother to set it, that value will be nil (no-value). With ?? (Nil Coalescing Operator), we can return the default value as expressed succinctly above.
So, ?? returns the value of the left variable if it is not nil. If it is nil, then the right variable (default) is returned. This can, of course, be used with Strings, custom types, etc. And it is useful as long as the first variable is an optional.