Inlining @Environment access in SwiftUI

The @Environment modifier in SwiftUI is a core data-flow primitive, that allows one to access environment values set by the parent.

Example usage:

struct Foo: View {
    @Environment(\.colorScheme) var colorScheme

    var body: some View {
        Group {
            if colorScheme == .light {
                Text("Light")
            } else {
                Text("Dark")
            }
        }
    }
}

This is all well and good - but note that @Environment is implemented as a property wrapper and cannot be used without a housing View structure.

In prototyping code heavily reliant on @Environment, this can feel cumbersome and boilerplate-y. Hence, I wrote a simple generic wrapper to solve this problem:

public struct EnvironmentValueAccessView<EnvironmentValue, Content: View>: View {
    private let keyPath: KeyPath<EnvironmentValues, EnvironmentValue>
    private let content: (EnvironmentValue) -> Content

    @Environment var environmentValue: EnvironmentValue

    public init(
        _ keyPath: KeyPath<EnvironmentValues, EnvironmentValue>,
        @ViewBuilder content: @escaping (EnvironmentValue) -> Content
    ) {
        self.keyPath = keyPath
        self.content = content

        self._environmentValue = .init(keyPath)
    }

    public var body: some View {
        content(environmentValue)
    }
}

With EnvironmentValueAccessView now, we can express our example code as a simple inline expression:

        EnvironmentValueAccessView(\.colorScheme) { colorScheme in
            if colorScheme == .light {
                Text("Light")
            } else {
                Text("Dark")
            }
        }
 
9
Kudos
 
9
Kudos

Now read this

PresentationLink broken in Xcode 11 beta 3

PresentationLink (in SwiftUI) seems to be broken in Xcode 11 beta 3. It succeeds in presenting a modal view controller the first time, but stops working thereafter. As noted in this StackOverflow post, this seems to occur when embedding... Continue →