(2021/10/09 更新)
Viewが表示または消えた時に実行するアクションを指定方法を解説します。
環境
この記事の情報は次のバージョンで動作確認しています。
【Swift】5.5
【iOS】15.0
【macOS】Big Sur バージョン 11.6
基本的な使い方
Viewに対して下記のModifierを使用します。
1 2 3 |
.onAppear{ Viewが表示された時のアクション } |
対象Viewが表示された時に実行するアクションを、クロージャーで指定します。
View表示イベントにアニメーションが関連付けられている場合、クロージャはアニメーションの開始時に実行されます。
1 2 3 |
.onDisappear{ Viewが消えた時のアクション } |
こちらは、対象Viewが消えた時に実行するアクションを、クロージャーで指定します。
View表示イベントにアニメーションが関連付けられている場合、クロージャはアニメーションの終了時に実行されます。
使用例
テキストViewが表示されるあるいは消える時にメッセージを出力する例です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
struct ContentView: View { @State private var showingText = false var body: some View { ZStack { if showingText { Text("カピ通信") .font(.title) .padding() .background( RoundedRectangle(cornerRadius: 10) .fill(Color.green) ) .onAppear{ print("テキスト表示") } .onDisappear{ print("テキスト非表示") } } VStack { Spacer() Button("表示切り替え") { showingText.toggle() } } } } } |
画面遷移時のアクションを指定する
各画面のView階層の先頭Viewに対して使用すると、画面遷移時および終了時のアクション指定が可能です。
画面遷移のパターンによって発生条件が若干異なります。
NavigationViewによる画面遷移
NavigationViewを使った画面遷移の場合、NavigationViewの内側のViewが切り替わる動きになりますので、画面遷移した際に元のViewの終了イベントが発生します。
また、画面から戻ってきた際に新たに元のViewの表示イベントが発生します。
次のサンプルを実行し、動きを確認してみて下さい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
struct ContentView: View { var body: some View { NavigationView { VStack { Text("- 1st View -") NavigationLink(destination: SecondView()) { Text("2nd Viewへ") }.padding() } .onAppear{ print("1st Viewの開始") } .onDisappear{ print("1st Viewの終了") } } .onAppear{ print("初期画面開始") } .onDisappear{ print("初期画面終了") } } } struct SecondView: View { @Environment(\.dismiss) var dismiss var body: some View { VStack { Text("- 2nd View -") Button("画面を閉じる") { dismiss() }.padding() } .onAppear{ print("2nd Viewの開始") } .onDisappear{ print("2nd Viewの終了") } } } |
.onAppear()は画面遷移アニメーションの開始時に、.onDisappear()は画面遷移アニメーションの終了時に各々発生する為、遷移先画面が開始してから時間差があって遷移元画面が終了するのがわかります。
Sheetによる画面遷移
Sheetは元の画面の上に次の画面が重なる動きなので、NavigationViewとは異なり元の画面の終了処理は発生しません。
sheet()モディファイアのonDissmissプロパティで指定した処理はViewを閉じるAnimationの前に、実際に画面を消去するdismiss()で指定した処理はAnimationの後で実行されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
struct ContentView: View { @State private var showingSheet = false var body: some View { Text("- 1st View -") Button("Sheetを開く") { self.showingSheet.toggle() } .padding() .sheet(isPresented: $showingSheet, onDismiss: { print("2nd Viewを閉じる")}) { SecondView() } .onAppear{ print("1st Viewの開始") } .onDisappear{ print("1st Viewの終了") } } } struct SecondView: View { @Environment(\.dismiss) var dismiss var body: some View { Text("- 2nd View -") Button("画面を閉じる") { dismiss() } .padding() .onAppear{ print("2nd Viewの開始") } .onDisappear{ print("2nd Viewの終了") } } } |
TabViewによる画面遷移
TabViewでは、NavigationViewと同様画面が切り替わる動きになりますので、画面遷移時に元の画面の終了処理が発生します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
struct ContentView: View { var body: some View { TabView { FirstView() .tabItem { Image(systemName: "sun.max") Text("1st") } SecondView() .tabItem { Image(systemName: "cloud") Text("2nd") } ThirdView() .tabItem { Image(systemName: "cloud.rain") Text("3rd") } } } } struct FirstView: View { var body: some View { Text("1st View") .onAppear{ print("1st Viewの開始") } .onDisappear{ print("1st Viewの終了") } } } struct SecondView: View { var body: some View { Text("2nd View") .onAppear{ print("2nd Viewの開始") } .onDisappear{ print("2nd Viewの終了") } } } struct ThirdView: View { var body: some View { Text("3rd View") .onAppear{ print("3rd Viewの開始") } .onDisappear{ print("3rd Viewの終了") } } } |
画面遷移時のアクションでエラーになる場合
画面遷移時のアクションの内容によっては、実行時にエラーになるケースがあります。
実行するiOSのバージョンによっても動きが異なるようです。
対処方法は次の記事を参考にして下さい。