@Environment is a property wrapper that gives views access to shared dependencies—Calendar, Locale, ColorScheme, and others built into SwiftUI.
struct CalendarView: View {
@Environment(\.calendar) var calendar: Calendar
var body: some View { }
}But what about app-specific dependencies? Say you want an ImageFetcher available to any view that displays remote images, with caching across screens.
SwiftUI supports this through custom environment keys:
struct MovieCell: View {
@Environment(\.imageFetcher) var fetcher: ImageFetcher
var movie: Movie
private var poster: AnyPublisher<UIImage, Never> {
fetcher.image(for: movie.posterURL)
}
var body: some View { }
}Implementation
Two pieces are required: an EnvironmentKey and an extension on EnvironmentValues.
Define the key
EnvironmentKey requires a default value for your dependency:
public protocol EnvironmentKey {
associatedtype Value
static var defaultValue: Self.Value { get }
}struct ImageFetcherKey: EnvironmentKey {
static let defaultValue = ImageFetcher()
}The defaultValue is instantiated lazily on first access via @Environment.
Expose the property
Extend EnvironmentValues to provide the key path used with @Environment:
extension EnvironmentValues {
var imageFetcher: ImageFetcher {
get { self[ImageFetcherKey.self] }
set { self[ImageFetcherKey.self] = newValue }
}
}That’s it. Any view can now access @Environment(\.imageFetcher).
Full implementation available here.