Swift Optionals
In this article, we will explain Swift Optionals.
What Are Optionals in Swift?
Swift has a type called Optional, which allows you to handle both the case where a value exists and the case where the value is nil with the same variable.
Optional is an enum that holds either a value or no value, wrapping the original data type.
When you want to define an Optional variable, you add a ? after the data type or specify it as Optional<Type>.
For example, if you want to define a constant of type Optional Int, you can write:
let value1: Int? = 100
let value2: Optional<Int> = 100
print(type(of: value1))
print(type(of: value2))
The result will look like this. You can see that the type is Optional<Int>.
Optional<Int>
Optional<Int>
Unwrapping Optionals in Swift
When you want to use the value stored in an Optional variable, you need to unwrap it.
If you are sure the value exists, you can force unwrap it by adding ! after the variable.
Be careful: if the value is nil, it will cause an error.
let value: Int? = 100
if value != nil {
print("Value = \(value!)")
} else {
print("No value exists.")
}
The result will be:
Value = 100
Optional Binding with if let
With Optional Binding, you can check whether an Optional variable has a value and, if it does, assign that value to a constant or variable and continue processing.
Optional Binding can be used with control statements like if or while.
The most common form is if let. The previous code can be rewritten using Optional Binding like this:
let value: Int? = 100
if let i = value {
print("Value = \(i)")
print(type(of: value))
print(type(of: i))
} else {
print("No value exists.")
}
The result will be that when value contains a value, it is unwrapped and assigned to i, and the if block is executed.
The data type of value is Optional<Int>, while the type of i is Int, confirming that it has been unwrapped.
Value = 100
Optional<Int>
Int
A constant defined with if let can only be used within the if block.
Optional Binding with guard let
Another frequently used Optional Binding is guard let.
The guard statement must always be used with else. When the condition is true, execution continues; when it's false, you must exit the scope using return or throw.
With guard let, you can unwrap an Optional only if it contains a value, and then continue processing safely.
Unlike if let, constants defined with guard let can be used after the guard statement as well.
For example, in a function, you might write:
func greet(name: String?) -> String {
guard let name = name else {
return "No name"
}
return "Hello, \(name)"
}
print(greet(name: nil))
print(greet(name: "Sakura"))
The result will be:
No name
Hello, Sakura
This example is simple, but guard let is very useful when you want to make it explicit that a value must exist in order to continue processing.
Optional Chaining in Swift
If you want to safely access properties or methods of an object wrapped in an Optional without causing an error, you can use Optional Chaining.
The Optional Chaining operator is ?, which you add after the Optional variable before calling a property or method.
If the value is nil, the following property or method call will not be executed.
This is convenient because you don't need to check beforehand with an if statement whether the Optional is nil.
For example, if you have an Optional String and want to call the contains() method, you can write:
let s:String? = "abcde"
if s?.contains("c") == true {
print("c exists.")
}
The result will be:
c exists.
Providing Default Values with ??
When working with Optionals, you can use the ?? operator to provide a default value in case the Optional is nil.
For example, you can use ?? with Int() to handle invalid input like this:
let input = "ABC"
let i = Int(input)
print(i ?? "Invalid input")
The result will be Invalid input, because "ABC" cannot be converted to an Int, so i is nil. If the input were a numeric string, its value would be printed instead.
Invalid input
That's it for an overview of Optionals in Swift.