まず、作ってみます。
定型です。
private struct MyEnvironmentKey: EnvironmentKey {
static let defaultValue: String = "Default"
}
extension EnvironmentValues {
var myCustomValue: String {
get { self[MyEnvironmentKey.self] }
set { self[MyEnvironmentKey.self] = newValue }
}
}
extension View {
func myCustomValue(_ myCustomValue: String) -> some View {
environment(\.myCustomValue, myCustomValue)
}
}
デフォルトに "Default" という文字列を設定していますが、
SwiftUI の View であればどこでもプロパティラッパーを経由して利用できます。
入れ子になった View で使ってみます。
struct Root: View {
var body: some View {
First()
Second()
}
}
struct First: View {
@Environment(\.myCustomValue) var myCustomValue
var body: some View {
Text("First " + myCustomValue)
}
}
struct Second: View {
@Environment(\.myCustomValue) var myCustomValue
var body: some View {
Text("Secound " + myCustomValue)
Third()
}
}
struct Third: View {
@Environment(\.myCustomValue) var myCustomValue
var body: some View {
Text("Third " + myCustomValue)
}
}
「Scound」とか www
続いて、デフォルトの値を上書きして変更します。
Environment の値の変更時には、View のツリー構造を思い浮かべながら影響範囲を考えます。
変更箇所は一行追加のみです。
Enviroment 定義時に extension も作成していますので、それを使っても等価です。
struct Root: View {
var body: some View {
First()
Second()
.environment(\.myCustomValue, "Another") // *
//.myCustomValue("Another") // * extension
}
}
struct First: View {
@Environment(\.myCustomValue) var myCustomValue
var body: some View {
Text("First " + myCustomValue)
}
}
struct Second: View {
@Environment(\.myCustomValue) var myCustomValue
var body: some View {
Text("Secound " + myCustomValue)
Third()
}
}
struct Third: View {
@Environment(\.myCustomValue) var myCustomValue
var body: some View {
Text("Third " + myCustomValue)
}
}
Second() に付けた .environment() で更新しています。
影響範囲は「その下位の View すべて」となります。
SwiftUI には、あらかじめ用意された便利な Environment がたくさんあります。
その中から、さらに、加えて font を使ってみます。
var font: Font?
The default font of this environment.
👉 EnvironmentValues | Apple Developer Documentation
定義 (extension を含む) の記述は不要なので
ツリー構造だけ気にしながら、
好きなところですばやく上書きしていくことができます。
struct Root: View {
var body: some View {
First()
.environment(\.font, .caption) // *
//.font(.caption) // * extension
Second()
.environment(\.myCustomValue, "Another")
//.myCustomValue("Another")
.font(.largeTitle) // * extension
}
}
struct First: View {
@Environment(\.myCustomValue) var myCustomValue
var body: some View {
Text("First " + myCustomValue)
}
}
struct Second: View {
@Environment(\.myCustomValue) var myCustomValue
var body: some View {
Text("Secound " + myCustomValue)
Third()
}
}
struct Third: View {
@Environment(\.myCustomValue) var myCustomValue
var body: some View {
Text("Third " + myCustomValue)
.font(.caption) // * extension
}
}
プロパティラッパー @Environment の利用は不要で、
下位 View に適用されていきます。
さらに、それを上書きもできます。
しかし、「Scound」とか恥ずいわ。
🌝 まとめ
ある程度調べてからやってみたのですが、少しイメージと違いました。
- デフォルト値はプロパティとしてどの View でも取得できる。
- 値の変更時に範囲を考慮しながら上書きする。
- プロパティで取得しなくてもそのまま適用されるものもある。
ちなみに、GitHub で調べてみると一番使われてる Built-in EnvironmentValue は、
@Environment(\.dismiss) var dismiss
でした。タイプは DismissAction です。
👉 Environment | Apple Developer Documentation
👉 EnvironmentValues | Apple Developer Documentation
👉 EnvironmentKey | Apple Developer Documentation