サイトアイコン BergamotMagic

おそるおそるSwift 番外編1 ObservableObject ObservedObject

Swift5+Xcode11.6

 どこから頂いてきたのか記憶にないのですが、ディスクに保存されていた下のコードが理解できずに、いろいろ試行したときの備忘録です。
 結果から言うと、ObservableObjectは複数のViewで共用できるという話なのですが、本当に理解できたのかは”?”です。

import SwiftUI

class A: ObservableObject {
    @Published var property1:Int = 1
    @Published var flag:Bool = false
}

struct ContentView: View {
    @ObservedObject var a = A()
    var body: some View {
        VStack {
            Subview1(a:a)
                .position(x:200,y:300)
            if a.flag {
                    Subview2(a:a)
                Spacer()
                    .frame(height: 100)
            }
        }
    }
}

struct Subview1:View {
    @ObservedObject var a:A

    var body:some View {
        VStack {
            Text("property1 = \(a.property1)").padding()
            Button(action: {
                self.a.property1 += 1
            }) {
                Text("Click here to add 1")
                    .foregroundColor(Color.white)
                    .background(Color.green)
            }
            Toggle(isOn: $a.flag) {
                Text("Toggle to show Subview")
                    .foregroundColor(Color.black)
            }.frame(width:250)
        }
    }
}

struct Subview2:View{
    @ObservedObject var a:A
    var body:some View {
        VStack {
            Text("Subview")
            Text("property1 = \(a.property1)")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

 下の動画のように動きます。

https://bergamotmagic.tokyo/wp-content/uploads/2020/08/362041d3d762cf76dbd474fced45cc0d.mp4

わからなかったのは、Subview1(a:a)というところです。引数aにaを入れて渡すということになりますが混乱しました。そこで、Subview1(b:a)に変えてみました。どうなったかというと、下図のようにエラーが出ました。まあ、それはそうですね。引数bではなくaのままなので。

エラー画面(b:じゃなくてa:でしょ?)

 そこで、Subview1構造体の方も修正しました。

struct Subview1:View {
    @ObservedObject var b:A
    var body:some View {
        VStack {

            Text("property1 = \(b.property1)").padding()
            Button(action: {
                self.b.property1 += 1
            }) {
                Text("Click here to add 1")
                    .foregroundColor(Color.white)
                    .background(Color.green)
            }
            Toggle(isOn: $b.flag) {
                Text("Toggle to show Subview")
                    .foregroundColor(Color.black)
            }.frame(width:250)
        }
    }
}

 すると、正常に動作しました。当たり前といえば当たり前ですが、引数はaである必要はないことが分かりました。
 次の疑問は、@ObservedObjectの書式が
     @ObservedObject var a = A() (9行目)
  @ObservedObject var b:A   (24行目。ただし、先ほどの施行でaはbに変わっています。)
の2種類あることでした。必ずこうでなければならないのか確かめるために、
  @ObservedObject var b:A を
  @ObservedObject var b = A()
に変更してみたところ、正常に動作しました。どちらもa(又はb)をAクラス型のインスタンスとして宣言しているわけで、単に書式が違うだけですから、これも当たり前といえば当たり前です。
 ちなみに
  @ObservedObject var a = A() を
  @ObservedObject var a:A
に変更すると、エラーが出ました。

モバイルバージョンを終了