Within SwiftUI we may have a lot of options on how to handle data. To help us out with this, Apple has introduced a few propertyWrappers for us.
But to make everything clear may be a bit complicated at first. So I decided to check every wrapper and test the functionality behind it.
The list contains 15 items (at the moment of writing). So let’s review them all.
@AppStorage
A property wrapper type that reflects a value from UserDefaults and invalidates a view on a change in value in that user default.
This means that this wrapper performs re-render View on every change and store value in UserDefaults.
not secure and should not be used to store sensitive data.
@Binding
A property wrapper type that can read and write a value owned by a source of truth.
Use a binding to create a two-way connection between a property that stores data and a view that displays and changes the data. A binding connects a property to a source of truth stored elsewhere, instead of storing data directly. For example, a button that toggles between play and pause can create a binding to a property of its parent view using the Binding property wrapper.
Same as @State, but value stored non in the same View, and only observation is done and on any change, the view will re-render itself.
Here we have a TickObservable view that has a @Binding value - a value that is stored outside of this View but should be displayed and updated in this view.
ContentViewModel has some logic that generates updates (using a timer) - we may skip this as this point not important for a @Binding sample.
Content view - has declared @State property that changes every time as we receive an update from ViewModel.
Here, @Binding - an ideal solution for propagating changes down to hierarchy.
@Environment
A property wrapper that reads a value from a view’s environment. Use the Environment property wrapper to read a value stored in a view’s environment. Indicate the value to read using an EnvironmentValues key path in the property declaration.
In most cases, this wrapper is used for accessing system-defined values, but it’s also possible to define their own Environment property and access it from any View.
@EnvironmentObject
A property wrapper type for an observable object supplied by a parent or ancestor view.
An environment object invalidates the current view whenever the observable object changes. If you declare a property as an environment object, be sure to set a corresponding model object on an ancestor view by calling its View/environmentObject(_:) modifier.
A convenient way to pass data indirectly, instead of passing data from parent view to child to grandchild, especially if the child view doesn’t need it.
@FetchRequest
A property wrapper type that makes fetch requests and retrieves the results from a Core Data store.
This change is related to CoreData. Thankfully to this propertyWrapper, we may remove the boiler part of work related to CoreDataFetchRequest preparation for SwiftUI. To do so, we simply set environment value with keypath managedObjectContext to current context and we are ready to go.
@FocusedBinding
A convenience property wrapper for observing and automatically unwrapping state bindings from the focused view or one of its ancestors.
Can be used as part of the mechanism of an alternative way to pass data between View (like ObservableObject)
A property wrapper type that updates a property while the user performs a gesture and resets the property back to its initial state when the gesture ends.
U can’t change this property directly - is a get-only property.
@Namespace
A dynamic property type that allows access to a namespace defined by the persistent identity of the object containing the property (e.g. a view).
In other words - this is an identifier for view with the same ID in a different hierarchy. Can be used for creating an animation of geometry transition from one view to another. Good use-case scenario - “Hero”-animation.
Default animation - fadeIn and fadeOut.
@ObservedObject
A property wrapper type that subscribes to an observable object and invalidates a view whenever the observable object changes.
Should be a reference type. A class should define at least one @Published property and if u want to observe that value, mark that object as @ObservedObject. Class should conform to ObservableObject. So this can be compared to @State property, but in a separate class - result from the same.
@ScaledMetric
A dynamic property that scales a numeric value.
relativeTo - define whats font size to match
@SceneStorage
A property wrapper type that reads and writes to persisted, per-scene storage.
This property acts like a @State but unlike @State it’s persistent. Also, this persistence applied only to selected Scene only.
Thus, @SceneStorage is like @State, we can move it as binding to another view using the $ symbol.
not secure and should not be used to store sensitive data.
@State
A property wrapper type that can read and write a value managed by SwiftUI.
Use this wrapper on values that are owned by View and can be changed by View. Apple recommends that this property always be a private one, in other cases View may not be rebuilt.
You should only access a state property from inside the view’s body, or from methods called by it. For this reason, declare your state properties as private, to prevent clients of your view from accessing them. It is safe to mutate state properties from any thread. source
Put a breakpoint in the body and press the button - as soon as u do, u will observe, that body is rebuilt (re-rendered) and a new value applied.
Use the state as the single source of truth for a given view.
@State property also can be used as dataValue via wrappedValue or as bindingValue via $ followed by propertyName - a projected value (Binding<Value>). Usually, this is used for passing a value down to a view hierarchy.
@StateObject
A property wrapper type that instantiates an observable object.
In other words - this is @ObservedObject that does not recreate whenever and works like @State.
@UIApplicationDelegateAdaptor
A property wrapper that is used in App to provide a delegate from UIKit.
You also can conform HelloAppDelegate to ObservableObject and later share this delegate and use callbacks.
For macOS there is @NSApplicationDelegateAdaptor
@ViewBuilder
A custom parameter attribute that constructs views from closures.