Swift is known for its safety features and expressive syntax, and one of its powerful constructs is the optionals system. Optionals allows us to represent values that may or may not be present. However, working with optional bindings can sometimes lead to code that’s verbose and harder to read. To address this, we can leverage Swift’s Custom operators feature to create a concise and elegant operator that we can use to nil Coalesce Optional Binding.
1
2
3
4
5
6
public func ??<T>(lhs: Binding<Optional<T>>, rhs: T) -> Binding<T> {
Binding(
get: { lhs.wrappedValue ?? rhs },
set: { lhs.wrappedValue = $0 }
)
}
The custom operator ??<T>
takes two arguments:
- lhs: A Binding to an optional value of type T.
- rhs: A non-optional value of type T.
lhs: Stands for “left-hand side.” In this case, it refers to the first argument we are passing to the custom operator, which is a Binding to an optional value of type T.
rhs: Stands for “right-hand side.” Which is the second argument passed to the custom operator, which is a non-optional value of type T.
The purpose of this operator is to make it easier to unwrap the optional value within the Binding and provide a default value (rhs) in case the optional value is nil. This eliminates the need for explicit unwrapping or optional bindings, which will make our code more readable and concise.
Alright let’s break down how the operator works:
The get
closure retrieves the wrapped value of the left-hand side (lhs) Binding. If the wrapped value is not nil, it returns that value; otherwise, it returns the default value (rhs).
The set
closure is responsible for updating the wrapped value of lhs when the new value is set. It assigns the new value to lhs.wrappedValue.
Here’s an example of how we might use this custom operator:
1
2
3
4
5
6
7
@State private var optionalValue: Int? = 42
@State private var defaultValue = 0
var body: some View {
let binding = $optionalValue ?? defaultValue
Text("Value: \(binding.wrappedValue)")
}
In this example, the binding created using the custom operator ensures that if optionalValue is nil, it falls back to the defaultValue, providing a neat way to handle optionals without verbose unwrapping code.