🥑

@EnvironmentObjectとはどう使う?

2024/03/13に公開

📕Overview

https://developer.apple.com/documentation/swiftui/environmentobject

A property wrapper type for an observable object that a parent or ancestor view supplies.

親または祖先ビューが提供するobservableオブジェクトのプロパティラッパータイプ。

どのような目的で使うのか、どんな意味なのかというと、違うページで状態を共有することができます。

こちらの動画が参考になりました。
https://www.youtube.com/watch?v=xEqP7jbU0x0

🧷summary

状態をグローバルに扱うことができるDataExampleというクラスを作成します。ObservableObjectというプロトコルに準拠しています。これは呼び出すことで、値を保持している stored propertyを使い、テキストとカウンターの数値をどこのページでも渡すことができます。
もし@Stateだったら、ページを作っているstructの中でしか状態を扱えないですね。

VStackに、.で繋げているenvironmentObjectは、Data classであるDataExampleを紐つけています。
TextBlockViewとSampleViewは別Viewでこちらでは、EnvironmentObjectを使って、DataExampleの状態を渡しています。

import SwiftUI

 class DataExample : ObservableObject {
     var text = "Counter"
     var counter = 0
}

struct EnvironmentObjectView: View {
     var data = DataExample()
    
    var body: some View {
        VStack {
            TextBlockView()
            SampleView()
        }
        .environmentObject(data)
    }
}

#Preview {
    EnvironmentObjectView()
}

TextBlockViewは、図形の中に、EnvironmentObjectを使って、DataExampleの状態を渡しています。
図形をTapすると、onTapGestureの機能で、counterプロパティの状態が更新されて数字が増えて行きます。他のページでも状態が共有されているので、他のSampleViewでも値は増えていきます。

import SwiftUI

struct TextBlockView: View {
    @EnvironmentObject var data : DataExample
    
    var body: some View {
        ZStack {
            Rectangle()
                .frame(width: 200, height: 60)
                .foregroundColor(.blue)
                .cornerRadius(9)
            Text("\(data.text) : \(data.counter)")
                .foregroundColor(.white)
        }
        .onTapGesture {
            data.counter += 1
        }
    }
}

#Preview {
    TextBlockView()
}

SampleViewには、ボタンがないので値は増やせないですね。でもTextBlockViewで状態が変更されると、プロパティの値は変化します。状態を監視しているからできるのでしょうね。いや状態が共有されているのか...

import SwiftUI

struct SampleView: View {
    @EnvironmentObject var data : DataExample
    
    var body: some View {
        Text("\(data.text) : \(data.counter)")
    }
}

#Preview {
    SampleView()
        .environmentObject(DataExample())
}

図形をTapするとこんな感じで別のViewのカウンターも増えていきます。

🧑‍🎓thoughts

今回は、@EnvironmentObjectを使って違うページで状態を扱うことをやってみました。データにアクセスするが正しいのかもしれない。最近よく使うことが多かったので、SwiftUIの知識のアウトプットのために調べてロジックを書いてみました。

わかりやすくて参考になる日本語の記事もありました。
https://ios-docs.dev/swiftui-environmentobject/

Discussion