How to get Binding via dollar prefix in SwiftUI
Issue #488
The dollar is not a prefix, it seems to be a generated code for property wrapper, and each kind of property wrapper can determine which value it return via this dollar sign
State and ObservedObject are popular property wrappers in SwiftUI
State
Read State
A persistent value of a given type, through which a view reads and monitors the value.
If we have a simple State, we can access its 3 forms
1 | @State private var image: UIImage |
and here is what
1 | image // UIImage |
Also, with State, we can access Binding via projectedValue
1 | _image.projectedValue // Binding<UIImage> |
ObservableObject
Read ObservedObject
For a simple ObservableObject, we can see its 3 forms
1 | class ViewModel: ObservableObject { |
1 | @ObservedObject var viewModel: ViewModel = ViewModel() |
1 | viewModel // ViewModel |
If we view the source code of ObservableObject, we can see its Wrapper which uses dynamicMemberLookup to provide Binding
1 | @propertyWrapper public struct ObservedObject<ObjectType> : DynamicProperty where ObjectType : ObservableObject { |
Derived State
If we have a struct with @State in a SwiftUI view, we can access its property as Binding. This derived state mechanism is done via Dynamic keypath member lookup feature of Swift 5.1
1 | struct ViewModel { |
Take a look at the interface of Binding
1 | /// A value and a means to mutate it. |
So if use $viewModel.image we can access its property as Binding
1 | viewModel.image // UIImage? |
Conclusion
So now we know how to get Binding from State and ObservableObject, and the mysterious dollar sign. These are both convenient but confusing at first, but if we use it more, it will make more sense and hopefully we can learn to do the same for our own property wrappers