read

Environment is a very powerful way to pass data from parent down to children.

It is like a global singleton.

Don’t cringe, because that’s the direction SwiftUI is taking. So embrace it.

1. Custom Environment

The steps involve creating a key, injecting into EnvironmentValues, and then passing it (from parent to children).


/// 1. Declare a key with the type, and a default
struct MyEnvironmentKey: EnvironmentKey {
    static var defaultValue: CGFloat { 0 }
}

/// 2. Provide extension to EnvironmentValues
extension EnvironmentValues {
    var foo: CGFloat {
        get { self[MyEnvironmentKey.self] }
        set { self[MyEnvironmentKey.self] = newValue }
    }
}

/// 3. Pass to children using `environment`
ParentView()
  .environment(\.foo, 1.23)

2. Custom EnvironmentObject

The difference is that EnvironmentObject does NOT require a key.

Because it simply uses the type as the “key”.

You start by creating your custom type, which has to implement ObservableObject. Yup, that’s the same view model you’ll have.

/// 1. Declare the custom type
class MyModel: ObservableObject {
    @Published var foo: String = "a"
}

struct ChildView: View {

    /// 2. Use `@EnvironmentObject` with the custom type
    @EnvironmentObject var model: MyModel

    var body: some View {
        Text(model.foo)
    }
}

/// 3. Parent to pass down the model
struct ParentView: View {
    @ObservedObject var model = MyModel()

    var body: some View {
        model.foo = "b" // eg. Parent could update it
        return VStack {
            ChildView()
            ChildView()
        }
        .environmentObject(model)
    }
}

NOTE: You must create your EnvironmentObject and set it from somewhere. If it is never set and the child view uses it, the app will crash.


Image

@samwize

¯\_(ツ)_/¯

Back to Home