Loading...

SwiftUIの@State, @Binding, @StateObject, @ObservedObject, @EnvironmentObjectの使い分け

なんとなくSwiftUIでは@Stateと@Bindingを使っていて、@StateObjectを使う必要あるのかなと思っていましたが、Hacking with Swiftというサイトの解説を読んで納得したので自分用のメモ。


@StateObject、@ObservedObject、@EnvironmentObject

・ObjectがついたProperty WrapperはObservable Objectプロトコルに準拠したclassのインスタンスに対してだけ使用できる。


class TestClass: ObservableObject {

    @Published var testString: String = "test"

}


・始めに宣言する親Viewでは@StateObjectを使い、渡された子Viewでは@ObservedObjectを使う(@Bindingと同じイメージ)。


struct ParentView: View {

    @StateObject var testClassInstance = TestClass()

    

    var body: some View {

        ChildView(testClassInstance: testClassInstance)

    }

}


struct ChildView: View {

    @ObservedObject var testClassInstance: TestClass

    

    var body: some View {

        Text(testClassInstance.testString)

    }

}


もしくは子Viewの引数に直接Observable Objectのイニシャライザを渡す。子View視点では上の場合と違いはない。


struct ParentView: View {

    var body: some View {

        ChildView(testClassInstance: TestClass())

    }

}


struct ChildView: View {

    @ObservedObject var testClassInstance: TestClass

    

    var body: some View {

        Text(testClassInstance.testString)

    }

}


親Viewで@StateObjectの代わりに@ObservedObjectを使ってしまってもアプリは動くが、謎のエラーの原因になるらしいので非推奨。


・.environmentObjectを使ってObservable Objectに適合したクラスのインスタンスを登録するとそれ以降のViewではどこでも@EnvironmentObjectを使ってそのインスタンスにアクセスできるようになる。


struct ParentView: View {

    var body: some View {

        ChildView().environmentObject(TestClass())

    }

}


struct ChildView: View {var

    body: some View {

        GrandsonView()

    }

}


struct GrandsonView: View {

    @EnvironmentObject var testClassInstance: TestClass

    

        var body: some View {

            Text(testClassInstance.testString)

        }

}



@Stateと@StateObjectの使い分け

・普通のプロパティ→基本的に@State

・classを使いたい場合→@StateObject

・EnvironmentObjectを使いたい場合→@StateObject

私は上記の考え方で使い分けることにしました。

いろんなViewで使うプロパティはいちいち引数に書くのが大変なのでEnvironmentObjectを使います。ただし、ObservableObjectに適合したclassを自分で作る必要があります。

@Stateではclassを監視できないので@StateObjectを使う必要がありますが、ただたくさんのプロパティをまとめたいだけならstructにしてしまう方法もあります。

SwiftUI 230362637469871038
ホーム item