[SwiftUI]@EnvironmentObjectの使用方法とハマりどころ
はじめに
EnvironmentObjectを始めて使用する際に結構な確率でハマる部分があります。
そのハマり箇所も含めて簡単にまとめてみました。
環境
・ macOS: Monterey
・ Xcode: 13.2
EnvironmentObjectの使用方法
EnvironmentObjectはSwiftUIのデータバインディングの仕組みの一つでアプリ内でデータを共有したい場合に使用します。
また使用する際、インスタンスの基となるクラスは"ObservableObject"プロトコルに準拠する必要があり、更新したデータを受け取るにはプロパティに"@Published"を付けます。
使用例としてはViewの監視をViewModelで行うのでViewModel側のプロトコルを"ObservableObject"に準拠させて使用する方法が多いかと思います。
使用例を参考に深めていただけると幸いです。
使用例
使用例ではTestViewModelというクラスにtestFlagというBool型のプロパティを持たせて、TestView1とでデータを更新した場合TestView2でも反映されるものを紹介します。
class TestViewModel: ObservableObject {
@Published var testFlag = false
}
struct TestView1: View {
@EnvironmentObject var testViewModel: TestViewModel
var body: some View {
VStack{
Toggle(isOn: $testViewModel.testFlag) {
Text("TestView1")
}
Text(testViewModel.testFlag ? "true" : "false")
}
}
}
struct TestView2: View {
@EnvironmentObject var testViewModel: TestViewModel
var body: some View {
VStack{
Toggle(isOn: $testViewModel.testFlag) {
Text("TestView2")
}
Text(testViewModel.testFlag ? "true" : "false")
}
}
}
struct TestView: View {
@EnvironmentObject var testViewModel: TestViewModel
var body: some View {
VStack{
TestView1()
TestView2()
}
.environmentObject(testViewModel)
}
}
これでTestViewのプレビューをみると以下の動作が確認できます。
動画よりTestView1とTestView2でインスタンス化したtestViewModelですが、それぞれのView内でデータを更新しているにも関わらず、他のViewでもリアルタイムで更新されている事が確認できます。
プレビューのエラー(ハマりどころ)
@EnvironmentObjectを使用したViewをプレビューで表示させたい場合必ずenvironmentObjectを付けないとエラーになります。
上記のTestViewを例に、プレビューをする時は以下のようにenvironmentObjectを付ける。
struct TestView_Previews: PreviewProvider {
static var previews: some View {
TestView()
.environmentObject(TestViewModel())
}
}
まとめ
誰かの役に立てばうれしいです。
Discussion