What is the role of "$" in Swift?
Today, I will explain what "$" is both in SwiftUI and pure Swift.
When it comes to SwiftUI
We can pass a variable by reference into a function so that the variable is modified by the function using an "&" prefix. Here is an example:
func SwapInt(_ a: inout Int, _ b: inout Int) -> {
let temp = a
a = b
b = temp
}
var a = 4
var b = 19
SwapInt(&a, &b) // now a is 19 and b is 4
Similar to pass-by-reference by pointer in C/C++, the variables can be swapped using the "inout" keyword and the "&" prefix.
In the context of SwiftUI, the "$" prefix works similarly. If a variable with the "$" prefix is passed to a view or modifier, SwiftUI creates a binding to the variable. The binding acts as a reference to a mutable state, allowing SwiftUI view to read and write the value of the state.
struct ContentView: View {
@State private var isOn = false
var body: some View {
VStack {
Toggle("Toggle", isOn: $isOn)
Text(isOn ? "On" : "Off")
}
}
}
In the code above, "isOn" can be update with the "Toggle", and the changes will be reflected in the "Text" view.
In conclusion, the "$" prefix is a necessary tool to create a binding so that SwiftUI can read and write the variables through the view.
When it comes to pure Swift
We often see the "$" sign followed by a number like $0
,$1
, and $2
in closures.
These are shorthand of argument names. Let me explain with examples.
Example 1
let numbers = [2, 3, 5, 7, 11]
let doubledNumbers = numbers.map { $0 * 2 } // [4, 6, 10, 14, 22]
// the code below has the same functionality
// let doubledNumbers = numbers.map { number in number * 2 }
Example 2
let asciiSmall = [(97, "a"), (98, "b"), (99, "c")]
let asciiLarge = asciiSmall.map { ($0 - 32, $1.uppercased) }
// asciiLarge is [(65, "A"), (66, "B"), (67, "C")]
In the example 1, we can access each element in "numbers" with "$0" (only "$0" is valid in this case because it is a single array). Therefore, map
returns doubled values of each element in "numbers".
In the example 2, "$0" refers to the first element in each tuple (Int, String)
of the array, and "$1" refers to second element in each tuple. As a result, map
returns [(65, "A"), (66, "B"), (67, "C")]
.
In simple terms, "$" followed by a number is a way to access each element in the map
method's closure.