【SwiftUI】親ビューのメソッドを子ビューで呼び出す方法

この記事からわかること

  • SwiftUIメソッド操作
  • 親ビューのメソッドを子ビューから呼び出す方法
  • 親側のプロパティを子側から操作することもできる

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

Swift UIでアプリ開発中に親ビューのメソッドを子ビューから呼び出したい場面が発生しました。今回はその解決法をまとめていきたいと思います。

前説明とエラー

ファイル構造


struct ContentView: View {
    
    @State  var user:String = "ame"
    @State  var greeting:String = "Hello"
    
    func changeJP(){
        user = "あめ" 
        greeting = "こんにちは" 
    }
    
    var body: some View {
        VStack {
            Text("\(user)さん、\(greeting)!")
            ChildView()
        }
    }
}

struct ChildView: View {
    
    var body: some View {
        Button(action: {
//            親のchangeJP()を呼び出したい
        }, label: {
            Text("親のプロパティをリセット")
        })
    }
}

Swift UIのView構造体の中に定義しているメソッドは基本的には他のビューから呼び出すことができません

当たり前ですがそのまま呼び出そうとCannot find 'changeJP' in scopeといったscopeエラーになってしまいます。

親ビューのメソッドを子ビューから呼び出す方法

親ビューのメソッドを子ビューから呼び出す手順は以下の通りです。

ここではクロージャ(関数)を引数として渡せる仕様を用いて呼び出せるようにしていきます。関数とクロージャは厳密には異なります。

子ビューに空のメソッドを用意

まずは子ビュー側に空のメソッドを用意します。変数parentFunctionを宣言し、クロージャ型(?)としておきます。返り値が無い場合はVoid型を明示的に指定しておきます。

var parentFunction: () -> Void

親ビューのメソッドに倣った空のメソッドを定義するので、引数や返り値があるメソッドの場合は以下のように引数や返り値の型を指定します。

var parentFunction: (Int,String) -> Bool

子ビュー内で呼び出す際は下記のようにselfをつけて記述します。これで親ビューのメソッドを呼び出しているのと同等になります。

self.parentFunction()

struct ChildView: View {
    var parentFunction: () -> Void
    
    var body: some View {
        Button(action: {
            self.parentFunction()
        }, label: {
            Text("親のプロパティをリセット")
        })
    }
}

まだ動作しないので親ビューからメソッドを子ビューの引数として渡していきます。

SwiftUIではプレビュー表示するための関数がなく、エラーが出てしまうので空の関数を引数として渡しておきます。

struct ChildView_Previews: PreviewProvider {
    static var previews: some View {
        ChildView(parentFunction: {})
    }
}

親ビューからメソッドを渡す

子ビュー側に空のメソッドを用意したことで、親ビューから子ビューを呼び出す際に、引数parentFunctionメソッドを渡すことが必須条件になります。


struct ContentView: View {
    
    @State  var user:String = "ame"
    @State  var greeting:String = "Hello"
    
    func changeJP(){
        user = "あめ"
        greeting = "こんにちは"
    }
    
    var body: some View {
        VStack {
            Text("\(user)さん、\(greeting)!")
            ChildView(parentFunction: changeJP)
        }
    }
}

これで親のメソッドを子側から実行することができました。

この方法であれば今回のように親側のプロパティを子側から操作することもできるので汎用性が高いと思います。

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index