Welcome to an exciting SwiftUI tutorial where we'll create a recipe app! Using SwiftUI's NavigationStack,…
Using SwiftUI @Environment
The SwiftUI @Environment
property wrapper allows views to access shared data and respond to changes in the environment, such as interface styles, locale, and custom data defined by the app. This feature is crucial for creating adaptive and responsive SwiftUI apps.
Let’s learn how to use it:
Imagine a Magic Box: Think of UserSettings
as a magic box that holds a secret – whether it’s night or day in our app world. Add it to the main file of our app.
@Observable class UserSettings { var isNightTime = false var userName: String = "" } @main struct MyApp: App { @State private var settings = UserSettings() var body: some Scene { WindowGroup { ContentView() .environment(settings) } } }
Put the Magic Box in a Treasure Chest: Place the magic box in our main view, the ContentView
, so all other views can find it.
struct ContentView: View {
@StateObject var settings = UserSettings()
var body: some View {
// Other views will go here
.environmentObject(settings)
}
}
Create a Switch to Change Day to Night: Make a switch in ContentView
that changes our secret in the magic box. Make a Window to See the Secret: In another view, ChildView
, create a window to see if it’s night or day.
import SwiftUI
struct DataFlow_Environment: View {
@Environment(UserSettings.self) private var settings
private var isNightTimeBinding: Binding<Bool> {
Binding(
get: { self.settings.isNightTime },
set: { self.settings.isNightTime = $0 }
)
}
var body: some View {
VStack {
Toggle(isOn: isNightTimeBinding) {
Text("Toggle Night Mode")
}
Text(settings.isNightTime ? "Night" : "Day")
Text(settings.userName)
}
}
}
See the Magic Happen: When you switch the toggle in ContentView, ChildView will show if it’s night or day
This is a simple way to learn about @Environment
in SwiftUI. It’s like sharing secrets between different parts of your app!
If you noticed we created a workaround to switch day and night. But most of the time @Environment
is intentionally read-only to align with SwiftUI’s data flow principles, ensuring a clear separation between different types of data and minimizing unintended side effects across the app.
We can also reach same binding functionality using this new Bindable approach.
import SwiftUI
struct DataFlow_Environment: View {
@Environment(UserSettings.self) private var settings
var body: some View {
@Bindable var settings = settings
VStack {
Toggle(isOn: $settings.isNightTime) {
Text("Toggle Night Mode")
}
Text(settings.isNightTime ? "Night" : "Day")
Text(settings.userName)
}
}
}
Using @Environment
in SwiftUI is ideal when you need to share data across multiple views or respond to system-wide changes. It’s beneficial in situations where passing data through initializers becomes cumbersome or impractical.
Examples of @Environment
Use Cases:
- Theme Settings: Applying user-selected themes (like dark mode) across all views in an app.
- Localization and Accessibility: Adjusting text size or localizing content based on user settings.
- User Authentication State: Reflecting login status on various UI components without passing the state explicitly.
- Device Orientation and Size Class: Adapting UI layout based on the device’s orientation and size class.
- Environment Overrides: Customizing elements like fonts and colors across multiple views.
@Environment
simplifies state management by providing a centralized way to access and modify shared data, enhancing code reusability and maintainability.
For more details and examples, check out Apple’s documentation on @Environment
.