SwiftUI

SwiftUI ビューからビューへの引数の渡す場合の書き方

多くのプログラムの機能として存在する引数を付けてサブプロをCallするときパラメータの書き方は、どうするっていう疑問です。

最近、SwiftUIを勉強しています。
Viewがひとつだけのものの作り方しか知らなかったのですが、最近、2つ以上のビューをひとつのプログラムで制御する練習問題に、ぶち当たりました。(笑)

そうすると、どうしても、ある画面で入力した変数の内容を、もうひとつ画面で参照する必要が出てくるため
ビュー間の、値の受け渡しは、どうやるの?ってことが重要解決問題になりました。

以下ソースが完成形です。

import SwiftUI

// View間で、受け渡しをしたい値を保持するクラスの定義
class Data_class : ObservableObject {
    @Published var koumokuA = "ABC" //初期値をいれないと面倒なのでなにか入れる
}

// 親ビュー
struct ContentView: View {
    // クラスからインスタンスを生成
    @ObservedObject var instance_Name = Data_class()

    var body: some View {
        if (instance_Name.koumokuA == "ABC") {
            view_A(instance_ko1:instance_Name)  // 最初は必ずここを通るように作る
        } else {
            view_B(instance_ko2:instance_Name)
        }
    }
}

// 子ビューA
struct view_A: View {
    // インスタンスを生成するが、親から指定されたインスタンス名と合致して値が渡る
    @ObservedObject var instance_ko1 = Data_class()

    var body: some View {
        VStack {
            Text("項目Aの値は、\(instance_ko1.koumokuA)")
            Button("ボタンを押すと項目の値をZZZにします。"){instance_ko1.koumokuA = "ZZZ"}
            // ボタンが押されたら 監視下の値を変化させ親ビューif文のelse側を表示させる。
        }
    }
}
// 子ビューB
struct view_B: View {
    // インスタンスを生成するが、親から指定されたインスタンス名と合致して値が渡る
    @ObservedObject var instance_ko2 = Data_class()   // インスタンスを生成

    var body: some View {
        Text("項目Aの値は、\(instance_ko2.koumokuA)")
    }
}

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

struct から struct への値渡しの方法と言っても良いのですが

SwiftUIのビューは、必ず struct でできているらしいので、structから、struct への引数渡し方法 と題名を変更しても良いのですが。ま、とにかく調べに調べました。見つけたサンプルが皆さん、ObservableObject, ObservedObject(似てますよね。この2つ、一見して同じかと勘違いしました),Environment, EnvironmentObjects等々なにか特殊なものを使うと書いているんですね。

本題とは、少しずれるのですが

サンプルは、結局ObservableObjectObservedObjectを使用しました。
なので、このサンプルではインスタンス(名)を渡す例ということになります。

上記サンプルの説明を、しますね。

①クラスを用意(データをいれるための変数も書きます。)※これは本題とは少しずれてはいますが
ポイントは、クラス名の後に ObservableObject と書くことです。それと変数名の前には、@Published と書くことです。これにより、また余談ですがSwiftUIの監視下に入り、値が変化すると、Viewが再描画されるとのことです。

// View間で、受け渡しをしたい値を保持するクラスの定義
class Data_class : ObservableObject {
    @Published var koumokuA = "ABC" //初期値をいれないと面倒なのでなにか入れる
}

②親ビューにて、上記クラスを使用してインスタンスを生成します。これが元ですね。
インスタンス名は、instance_Name としました。

    // クラスからインスタンスを生成
    @ObservedObject var instance_Name = Data_class()

③そして、これがViewからViewへの値の渡し方

            view_A(instance_ko1:instance_Name)  // 最初は必ずここを通る...

ビュー名(callする子側の変数名:callする親側の変数名) 

と書くのが正解のようです。
端切れの悪い書き方で、すみません。正解が出ているサイトを最後まで見つけられませんでしが、これが正解だと思います。

ビュー名(callする子側の変数名:callする親側の変数名) と書くのが正解のようです。

今回のサンプルは、クラス(というかインスタンス)を渡しているので、インスタンスは参照型らしく、これにより、渡したい値を子側に渡すだけではなく子側で値を変更しても、その変更後の値が親側で受け取れるということのです。試しました。そうでした。

今回、インスタンス名を渡しましたが 、通常のvar 文字型でも、同じ方法
呼び出すView名(こちらがわの変数名:相手側の変数名)で、値を渡すことができました。
その場合は、一方通行で、親から子へ値が渡るだけで、その逆はできませんでした。