・他のビューで使用するために、この変数を別のクラスや構造体の中に置き、テキストフィールドのあるビューでインスタンス化して使用しようとすると、ビルドはできるものの実行するとクラッシュします。
@State はビューの中でのみ宣言できます。
ビューの外で使用する場合は ObservableObject と @Published を使用します。
Swift
1import SwiftUI
2
3class ViewModel: ObservableObject {
4 @Published var name: String = ""
5}
6// ObservableObject は AnyObject を継承するので class でのみ使用可能です
7// また @Published を付けた変数を変更すると、参照するすべての箇所に変更が伝播されます
8
9struct TextFieldView: View {
10 @ObservedObject var vm = ViewModel()
11 // ObservableObject を利用する側は @ObservedObject をつける
12
13 var body: some View {
14 VStack {
15 TextField("Placeholder", text: $vm.name)
16 Text("(vm.name)")
17 }
18 }
19}
@EnvironmentObjectを用いると複数のビューで状態変数を共有できるという方法もあるようですが、その詳しいやり方もよく分かっていません。
共有するには @State を @Binding するか ObservableObject をバケツリレーのように引き渡すことで行えます。
Swift
1// Binding の例
2import SwiftUI
3
4struct FirstView: View {
5 @State var name: String = ""
6
7 var body: some View {
8 VStack {
9 SecondView(name: $name) // Binding へ渡す時は $ をつける
10 Text("(name)")
11 }
12 }
13}
14
15struct SecondView: View {
16 @Binding var name: String
17
18 var body: some View {
19 VStack {
20 TextField("Placeholder", text: $name)
21 ThirdView(name: $name)
22 }
23 }
24}
25
26
27struct ThirdView: View {
28 @Binding var name: String
29
30 var body: some View {
31 Text(name)
32 }
33}
Swift
1// ObservableObject の例
2import SwiftUI
3
4class ViewModel: ObservableObject {
5 @Published var name = ""
6}
7
8struct FirstView: View {
9 @ObservedObject var vm = ViewModel() // インスタンスを生成
10
11 var body: some View {
12 VStack {
13 SecondView(vm: vm) // $ は不要
14 Text("(vm.name)")
15 }
16 }
17}
18
19struct SecondView: View {
20 @ObservedObject var vm: ViewModel
21
22 var body: some View {
23 VStack {
24 TextField("Placeholder", text: $vm.name)
25 ThirdView(vm: vm)
26 }
27 }
28}
29
30struct ThirdView: View {
31 @ObservedObject var vm: ViewModel
32
33 var body: some View {
34 Text(vm.name)
35 }
36}
バケツリレー方式だと、ビューの階層が深いと記述が煩雑になります。
この場合に @EnvironmentObject を使用します。
Swift
1import SwiftUI
2
3class ViewModel: ObservableObject {
4 @Published var name = ""
5}
6
7struct FirstView: View {
8 @ObservedObject var vm = ViewModel() // インスタンスを生成
9
10 var body: some View {
11 VStack {
12 SecondView()
13 .environmentObject(vm)
14 // SecondView 以下に @EnvironmentObject を設定
15
16 Text("(vm.name)")
17 }
18 }
19}
20
21struct SecondView: View {
22 @EnvironmentObject var vm: ViewModel
23
24 var body: some View {
25 VStack {
26 TextField("Placeholder", text: $vm.name)
27 ThirdView()
28 }
29 }
30}
31
32struct ThirdView: View {
33 var body: some View {
34 VStack {
35 Text("hoge hoge")
36 FourthView()
37 }
38 }
39 // 共有された変数を使わないビューは @EnvironmentObject の記述を省略可能
40}
41
42struct FourthView: View {
43 @EnvironmentObject var vm: ViewModel
44
45 var body: some View {
46 Text(vm.name)
47 }
48}
とりあえずは @State を @Binding して参照し、ビューの階層が増えてから ObservableObject や @EnvironmentObject の使用を検討すれば大丈夫です。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/09/20 07:11