Replacing EnvironmentKit with the new SwiftUI Entry macro

As SwiftUI becomes increasingly more capable over the years, custom workarounds to work around its limitations can become outdated as SwiftUI adds native support for what they aimed to solve.

This is what has happened with my open-source library EnvironmentKit, in which I tried to twist the Swift syntax to let us create custom environment values with less code.

I wrote about this experiment in this post, in which I also included code snippets to show you how I play around with Swift to make this work.

The end result made it a bit less painful to create custom environment values, where instead of this:

public struct CustomValue: Codable, Sendable { ... }

public extension CustomValue {
    
    static var standard = Self()
}

private extension CustomValue {

    struct Key: EnvironmentKey {

        static var defaultValue: CustomValue = .standard
    }
}

public extension EnvironmentValues {

    var customValue: CustomValue {
        get { self[CustomValue.Key.self] }
        set { self[CustomValue.Key.self] = newValue }
    }
}

public extension View {

    func customValue(_ value: CustomValue) -> some View {
        environment(\.customValue, value)
    }
}

you could let EnvironmentKit reduce the amount of code for each custom value quite a bit:

import EnvironmentKit

struct CustomValue: EnvironmentValue { 
    
    static var keyPath: EnvironmentPath { \.customValue }    
}

extension EnvironmentValues {

    var customValue: CustomValue {
        get { get() } set { set(customValue) }
    }
}

extension View {

    func customValue(_ value: CustomValue) -> some View {
        environment(value)
    }
}

If you skipped the view extension, all you basically had to do was to make the custom environment value type implement EnvironmentValue and define an EnvironmentValues extension.

However, with the new SwiftUI Entry macro, this becomes even easier. Just add an @Entry property for the type to EnvironmentValues, and you don’t have to specify a kepath at all:

public struct CustomValue: Codable, Sendable { ... }

public extension EnvironmentValues {

    @Entry var customValue = CustomValue()
}

public extension View {

    func customValue(_ value: CustomValue) -> some View {
        environment(\.customValue, value)
    }
}

The @Entry macro works for other value types as well. You can read more about this in Majid’s blog.

What now?

With this new macro, I have decided to remove EnvironmentKit altogether, since it will just clutter my GitHub account with an outdated technology that no one should use anymore.

If you need the code, or are curious to see how it was built, you can copy it from the old post that talked about how EnvironmentKit was built.

Discussions & More

If you found this interesting, please share your thoughts on Bluesky, Mastodon, and X. Also make sure to follow to be notified when new content is published.