What does the dollar sign do in Swift / SwiftUI?

This is very well explained in WWDC 2019 video 415. You are merely looking at one special case of a broad language feature, namely property wrappers.

A property wrapper (such as @State) is actually a way of referring to an instance of a type (usually a struct or enum) with the same name (such as State). The latter provides instructions for turning this instance property into a computed property whose getter and setter are the getter and setter for a certain computed property of itself (its wrappedValue). It also typically holds private storage backing that computed property.

Thus, after the declaration

@State var showFavoritesOnly = true

showFavoritesOnly is turned into a computed property, with its getter and setter supplied by the State struct. When you set showFavoritesOnly to true, that is routed through the State struct’s setter and ends up in a stored property of the State instance.

All of this implies that somewhere there is a State instance associated with your showFavoritesOnly. And there is, but it’s hidden from view. Its name, in case you’d like to see that State instance, is _showFavoritesOnly.

Okay, but when you say $showFavoritesOnly, you do not get a State struct; you get a Binding struct. Why? That’s because a property wrapper has a mechanism for specifying what the returned value from the $ name should be. In the case of State, it specifies that this value should be its own binding property, which is a Binding (see the docs: https://developer.apple.com/documentation/swiftui/state).

By an amazing coincidence, Toggle’s isOn initializer takes a Binding (again, see the docs, https://developer.apple.com/documentation/swiftui/toggle/3232112-init). You could not have set the Toggle’s isOn to showFavoritesOnly even if you wanted to! Instead, you set it to the Binding<Bool> supplied by the State instance, so that the Toggle has automatic two-way communication with the State object. The SwiftUI framework enforces its own correct usage; a Toggle can exist only in relation to some binding that acts as the underlying source of truth for its on/off state. And because it’s a binding, not a mere Bool, communication works in both directions: when the user taps the switch in the Toggle, the change in value flows “up” to the State variable by way of the binding.

Leave a Comment