What is the role of "$" in Swift?

·

2 min read

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.