LoginSignup
0
1

More than 1 year has passed since last update.

SwiftUIのProperty Wrappersの使い方 その2

Posted at

関連記事

SwiftUIのProperty Wrappersの使い方 その1
https://qiita.com/ryo_shiraishi6352/items/0b8eb768207b455f0387

StateObjectの使い方

@Stateは値型のプロパティに付加しますが参照型のクラスのプロパティには@StateObjectを付加します。
@StateObjectを付加するクラスにはObservableObjectプロトコルに準拠させ、監視するプロパティには@Publishedを付加します。
@Publishedを付加した値をBindingに渡したいときには@StateObjectを付加した変数の前に$を付けます。

import SwiftUI

struct StateObjectContentView: View {
    @StateObject var value = StateObjectValue(value: 0)
    
    var body: some View {
        VStack {
            HStack {
                Text("参照と更新")
                    .padding()
                Button(action: {
                    self.value.value += 1
                }) {
                    Text(String(self.value.value))
                        .padding()
                }
            }
            HStack {
                Text("@Bindingに渡す")
                    .padding()
                Picker("stateValue", selection: self.$value.value) {
                    ForEach(0...99, id: \.self) { v in
                        Text(String(v))
                    }
                }
            }
        }
        .frame(maxHeight: .infinity, alignment: .top)
    }
    
    class StateObjectValue: ObservableObject {
        @Published var value: Int
        
        init(value: Int) {
            self.value = value
        }
    }
}

struct StateObjectContentView_Previews: PreviewProvider {
    static var previews: some View {
        StateObjectContentView()
    }
}

スクリーンショット 2022-08-24 7.15.10.png

ObservedObjectの使い方

@Bindingのように外のViewからクラスを受け取りたいときには@ObservedObjectを付加します。
@Publishedを付加した値をBinding引数に渡したいときには@ObservedObjectを付加した変数の前に$を付けます。

import SwiftUI

struct ObservedObjectContentView: View {
    @StateObject var value = ObservableObjectValue(value: 0)
    
    var body: some View {
        ObservedObjectView(value: self.value)
    }
    
    class ObservableObjectValue: ObservableObject {
        @Published var value: Int
        
        init(value: Int) {
            self.value = value
        }
    }
    
    struct ObservedObjectView: View {
        @ObservedObject var value: ObservableObjectValue
        
        var body: some View {
            VStack {
                HStack {
                    Text("参照と更新")
                        .padding()
                    Button(action: {
                        self.value.value += 1
                    }) {
                        Text(String(self.value.value))
                            .padding()
                    }
                }
                HStack {
                    Text("@Bindingに渡す")
                        .padding()
                    Picker("stateValue", selection: self.$value.value) {
                        ForEach(0...99, id: \.self) { v in
                            Text(String(v))
                        }
                    }
                }
            }
            .frame(maxHeight: .infinity, alignment: .top)
        }
    }
}

struct ObservedObjectContentView_Previews: PreviewProvider {
    static var previews: some View {
        ObservedObjectContentView()
    }
}

スクリーンショット 2022-08-25 7.02.41.png

ObservableObjectを入れ子にした場合

ObservableObjectを入れ子にした場合、直接プロパティを変更してもViewの更新は行われません。  
@Binding@ObservedObjectを付加したプロパティを持つViewに渡すとViewの更新が行われます。  

import SwiftUI

struct ObservableObjectNestContentView: View {
    @StateObject var observableNestValue = ObservableNestValue1(value: 0, nest: ObservableNestValue2(value: 0))
    
    var body: some View {
        VStack {
            HStack {
                Text("参照と更新")
                    .padding()
                Button(action: {
                    self.observableNestValue.value += 1
                }) {
                    Text(String(self.observableNestValue.value))
                        .padding()
                }
                Button(action: {
                    self.observableNestValue.nest.value += 1
                }) {
                    Text(String(self.observableNestValue.nest.value))
                        .padding()
                }
            }
            HStack {
                Text("@Bindingに渡す")
                    .padding()
                BindingView(value: self.$observableNestValue.value)
                BindingView(value: self.$observableNestValue.nest.value)
            }
            HStack {
                Text("@ObservedObjectに渡す")
                    .padding()
                ObservedObjectView1(value: self.observableNestValue)
                ObservedObjectView2(value: self.observableNestValue.nest)
            }
        }
        .frame(maxHeight: .infinity, alignment: .top)
    }
    
    
    struct BindingView: View {
        @Binding var value: Int
        
        var body: some View {
            Button(action: {
                self.value += 1
            }) {
                Text(String(self.value))
                    .padding()
            }
        }
    }
    
    struct ObservedObjectView1: View {
        @ObservedObject var value: ObservableNestValue1
        
        var body: some View {
            Button(action: {
                self.value.value += 1
            }) {
                Text(String(self.value.value))
                    .padding()
            }
        }
    }
    
    struct ObservedObjectView2: View {
        @ObservedObject var value: ObservableNestValue2
        
        var body: some View {
            Button(action: {
                self.value.value += 1
            }) {
                Text(String(self.value.value))
                    .padding()
            }
        }
    }
    
    class ObservableNestValue1: ObservableObject {
        @Published var value: Int
        
        @Published var nest: ObservableNestValue2
        
        init(value: Int, nest: ObservableNestValue2) {
            self.value = value
            self.nest = nest
        }
    }

    class ObservableNestValue2: ObservableObject {
        @Published var value: Int
        
        init(value: Int) {
            self.value = value
        }
    }
}

struct ObservableObjectNestContentView_Previews: PreviewProvider {
    static var previews: some View {
        ObservableObjectNestContentView()
    }
}

スクリーンショット 2022-09-07 18.59.12.png

終わりに

SwiftUIのProperty Wrappersの使い方を実際にコードを書きながら動きを確認しました。  
基本的な使い方や画面が更新される範囲などを理解することができました。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1