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
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
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.