Feature-Scoped Environment Values
Context
Environment values work best when they belong to one feature boundary instead of the whole app. That keeps the dependency visible where it matters and avoids turning SwiftUI’s environment into a soft global state bucket.
The snippet
private struct FeatureFlagKey: EnvironmentKey {
static let defaultValue = false
}
extension EnvironmentValues {
var isProFeatureEnabled: Bool {
get { self[FeatureFlagKey.self] }
set { self[FeatureFlagKey.self] = newValue }
}
}
struct ProScreen: View {
@Environment(\.isProFeatureEnabled) private var isProFeatureEnabled
}
Why this works
The key lives close to the feature that uses it, so the meaning is obvious. The default value makes previews and tests predictable. And because the property name says what the feature needs, the screen stays readable without a long initializer.
This pattern also makes it easier to swap in test data. If a feature flag, theme token, or routing helper changes, you update one environment injection point instead of threading parameters through several wrapper views.
Use it when…
- a dependency belongs to one feature or module
- previews need a safe default
- several nested views need the same contextual value
Avoid it when…
- the dependency is really screen-owned data
- the value is central to the view’s business logic
- you are using environment just to avoid writing a parameter
Takeaway: Feature-scoped environment values keep context explicit without making every initializer noisy.