【SwiftUI】親ビューのメソッドを子ビューで呼び出す方法
この記事からわかること
- SwiftUIのメソッド操作
- 親ビューのメソッドを子ビューから呼び出す方法
- 親側のプロパティを子側から操作することもできる
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
Swift UIでアプリ開発中に親ビューのメソッドを子ビューから呼び出したい場面が発生しました。今回はその解決法をまとめていきたいと思います。
前説明とエラー
ファイル構造
- ContentView.swift(親ビュー)
- ChildView.swift(子ビュー)
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)
}
}
}
これで親のメソッドを子側から実行することができました。
この方法であれば今回のように親側のプロパティを子側から操作することもできるので汎用性が高いと思います。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。