In this post, we will see how to use Property Wrappers in our SwiftUI projects.
But first of all, what are Property Wrappers?
“Property wrappers in SwiftUI are a powerful feature that enables us to add extra logic to the properties of our SwiftUI views or data models.
They can manage storage, modify behavior, and add additional functionality in a reusable way.
SwiftUI introduces several property wrappers to help manage state and interface more effectively in our apps. Property wrappers abstract away the boilerplate code needed for common tasks, such as state management, environment settings and data binding.“
Let’s dive into some of the most commonly used property wrappers in SwiftUI:
@State
It is used to declare state within our SwiftUI view. It’s meant for simple properties that are stored directly within the view. When the state changes, SwiftUI automatically re-renders the view to reflect the updates.
import SwiftUI
import SwiftData
struct ContentView: View
{
@State private var counter = 0
var body: some View
{
VStack
{
Text("Count: \(counter)")
Button("Increment")
{
counter += 1
}
}
}
}
@Binding
It allows us to create a two-way binding between a state-managing property and a view that needs to read and write to it. It’s especially useful for passing state down the component tree without having to pass callbacks or use more complex state management solutions.
import SwiftUI
struct ContentView: View
{
@State private var name = "Hello from Damiano"
var body: some View
{
Text(name)
SecondView(name: $name)
}
}
import SwiftUI
struct SecondView: View {
@Binding var name: String
var body: some View {
TextField("Enter name", text: $name)
}
}
@ObservedObject / @Published
When we have a class that conforms to the ObservableObject protocol, we can use the @ObservedObject property wrapper to listen to changes within that object.
Combine this with the @Published attribute on properties within our observable object to automatically notify views of updates.
import Foundation
class ToggleViewModel: ObservableObject {
@Published var isToggled = false
}
import SwiftUI
struct ContentView: View
{
@ObservedObject var viewModel = ToggleViewModel()
var body: some View
{
Toggle("Toggle me!", isOn: $viewModel.isToggled)
}
}
@Environment
It provides access to environment values set by SwiftUI, such as themes, layout direction, and more. It’s useful for adapting our UI to different settings or states provided by the system.
import SwiftUI
struct ContentView: View
{
@Environment(\.layoutDirection) var layoutDirection
var body: some View
{
Text(layoutDirection == .leftToRight ? "LTR" : "RTL")
}
}
@AppStorage
It stores simple data persistently in UserDefaults.
Ideal for user preferences.
import SwiftUI
struct ContentView: View
{
@AppStorage("fontSize") var fontSize = 16
var body: some View
{
Stepper("Font Size: \(fontSize)", value: $fontSize)
}
}