vinhnx / notes

my today I learn (TIL) journal, includes everything that I found interesting, not necessarily relates to programming
44 stars 2 forks source link

SwiftUI @Environment #449

Open vinhnx opened 3 years ago

vinhnx commented 3 years ago

Environment is one way to pass data from one view to another.

To define an Environment value you need two things:


Example:

Create an environment key

struct SensitiveKey: EnvironmentKey {
  static let defaultValue: Bool = false
}

Introduce new value to Environment

Once we declare a data type and a key to access it, we introduce this newly create key/value to EnvironmentValues using extension.

extension EnvironmentValues {
  var isSensitive: Bool {
    get { self[SensitiveKey.self] }
    set { self[SensitiveKey.self] = newValue }
  }
}

Using

struct PasswordField: View {
  let password: String

  // we read environment value with `@Environment`
  @Environment(\.isSensitive) private var isSensitive

  var body: some View {
    VStack {
        // View then react to `isSensitive` value by redact the password if `isSensitive` is `true`.
        Text(password).redacted(reason: isSensitive ? .placeholder: [])
    }
  }
}

To use this PasswordField

struct ContentView: View {
  // we create a @State to control `isSensitive` env value
  @State private var isSensitive = false

   var body: some View {
       VStack {
         // bind the state var to a toggle
         Toggle("Sensitive", isOne: $isSensitive)

         // use the state var to override `isSensitive` env value of `PasswordField`
         PasswordField(password: "123456").isSensitive(isSensitive)
       }
   }
}

Conclusion

It might not be obvious that we can create a custom environment value, but we can do that. The steps to create one are not as straightforward as we usually do, but it isn't hard if you know how to do it.

Here is a summary of how to create a new environment value.

// Create an environment key
private struct NewKey: EnvironmentKey {
    static let defaultValue: DataTypeForNewValue = defaultValue
}

// Introduce new value to EnvironmentValues
extension EnvironmentValues {
    var newEnvironmentName: DataTypeForNewValue {
        get { self[NewKey.self] }
        set { self[NewKey.self] = newValue }
    }
}

// Add a dedicated modifier (Optional)
extension View {
    func newModifier(_ value: DataTypeForNewValue) -> some View {
        environment(\.newEnvironmentName, value)
    }
}

https://sarunw.com/posts/how-to-define-custom-environment-values-in-swiftui/

vinhnx commented 3 years ago

https://www.swiftbysundell.com/articles/swiftui-state-management-guide/