Skip to content

danielsaidi/EnvironmentKit

Repository files navigation

EnvironmentKit Logo

Version Swift 5.9 Swift UI MIT License Twitter: @danielsaidi Mastodon: @danielsaidi@mastodon.social

About EnvironmentKit

EnvironmentKit is a SwiftUI SDK that lets you define custom SwiftUI environment values with less code.

Instead of this standard boilerplate code:

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

private extension MyStyle {

    struct Key: EnvironmentKey {
        static var defaultValue: MyStyle = .standard
    }
}

public extension EnvironmentValues {

    var myStyle: MyStyle {
        get { self[MyStyle.Key.self] }
        set { self[MyStyle.Key.self] = newValue }
    }
}

public extension View {

    func myStyle(_ style: MyStyle) -> some View {
        environment(\.myStyle, style)
    }
}

You just need this:

struct MyStyle: EnvironmentValue { 
    
    static var keyPath: EnvironmentPath { \.myStyle }    
}

extension EnvironmentValues {

    var myStyle: MyStyle {
        get { get() } set { set(newValue) }
    }
}

extension View {

    func myStyle(_ style: MyStyle) -> some View {
        environment(style)
    }
}

Installation

EnvironmentKit can be installed with the Swift Package Manager:

https://github.com/danielsaidi/EnvironmentKit.git

You can also just copy the EnvironmentValue.swift file to your project, instead of using the package.

Getting Started

To define a custom environment value with EnvironmentKit, you just have to make your type implement EnvironmentValue by providing a default initializer (or default property values) and a keyPath:

struct MyViewStyle: EnvironmentValue {

    var color: Color = .red
    
    static var keyPath: EnvironmentKeyPath { \.myViewStyle }   
}

extension EnvironmentValues {

    var myViewStyle: MyViewStyle {
        get { get() } set { set(newValue) }
    }
}

Since EnvironmentKit knows about the keypath, you can now use a custom .environment(_:) view modifier that doesn't require a keypath, to inject custom values into the environment.

To make things even easier, you can provide a custom view modifier, like the native SwiftUI .buttonStyle(...):

extension View {

    func myViewStyle(_ style: MyViewStyle) -> some View {
        environment(style)
    }
}

You can now use your custom view modifier to apply custom styles in any part of your view hierarchy:

MyView()
    .myViewStyle(.customStyle)

Views can access injected values with the @Environment attribute and the custom key path:

struct MyView: View {

    @Environment(\.myViewStyle)
    let style

    ....
}

If no custom value is injected, EnvironmentKit will return a default value.

Environment value injection is MUCH more flexible than initializer or property injection, and can be used for all kind of types, like view styles, configurations, etc.

If you decide to give environment value injection a try, I hope that EnvironmentKit will make it a lot easier for you.

Future Work

My initial idea was for the keyPath property to be automatically resolved, by having EnvironmentValues provide a generic function that could be use instead of an explicit key path property.

It however seems Swift requires an actual property to be able to use it as a keypath in the .environment modifier. If we find a way to work around this limitation, the code would become even easier.

The dream would be for the type to just implement the EnvironmentValue protocol, and for EnvironmentKit to take care of the rest.

Documentation

The online documentation has more information on how to use this SDK.

Support my work

You can sponsor me on GitHub Sponsors or reach out for paid support, to help support my open-source projects.

Your support makes it possible for me to put more work into these projects and make them the best they can be.

Contact

Feel free to reach out if you have questions or want to contribute in any way:

License

EnvironmentKit is available under the MIT license. See the LICENSE file for more info.

About

EnvironmentKit is a SwiftUI SDK that let you create custom environment values with less code.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project