sheetのonDismissの変な挙動ですが、そもそも実装自体が変かもしれません。
ソースは以下です。
ContentView
からsheet
でSheetView1
を呼び出せるボタンを入れます。
SheetView1
中に自分を閉じるボタンとSheetView2
の表示フラグを変えて自分が消えるボタンを入れます。
ContentView
に設定されているSheetView2
は表示更新フラグに従ってSheetView2
を表示するようにします。
SheetView1
とSheetView2
にはそれぞれのonDismiss
関数が用意されており、どのビューが消えたかのログだけ出力してます。
import SwiftUI
struct ContentView: View {
@State private var isSheetView1Presented: Bool = false
@State private var isSheetView2Presented: Bool = false
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
Button(action: {
print("show sheet1")
isSheetView1Presented.toggle()
}, label: { Text("Open View 1") })
}
.padding()
.sheet(isPresented: $isSheetView1Presented, onDismiss: onSheet1Dismiss) {
SheetView1(isSheetView2Presented: $isSheetView2Presented)
}
.sheet(isPresented: $isSheetView2Presented, onDismiss: onSheet2Dismiss) {
SheetView2()
}
}
func onSheet1Dismiss() {
print("on sheet1 dismiss")
}
func onSheet2Dismiss() {
print("on sheet2 dismiss")
}
}
struct SheetView1: View {
@Environment(\.dismiss) var dismiss
@Binding var isSheetView2Presented: Bool
var body: some View {
Text("View1")
Button(action: {
dismiss()
}, label: { Text("Close") })
Button(action: {
dismiss()
print("show sheet2")
isSheetView2Presented.toggle()
}, label: { Text("Open View 2") })
}
}
struct SheetView2: View {
@Environment(\.dismiss) var dismiss
var body: some View {
Text("View2")
Button(action: {
dismiss()
}, label: { Text("Close") })
}
}
#Preview {
ContentView()
}
挙動の確認だけですので、画面はシンプルでこんな感じです。
さてと、ここからが問題です。
SheetView1
のOpen View 2
ボタンを押してSheetView2
を開き、SheetView2
のClose
ボタン押したらContentView
に戻りますが、onDismiss
に設定された関数はどのように呼び出されるでしょうか?
読み通りに行くと、SheetView2
を開く時に、SheetView1
は自分が消えますので、ここでがonSheet1Dismiss
呼ばれ、SheetView2
のClose
ボタン押した時に、SheetView2
も消えますので、ここでがonSheet2Dismiss
呼ばれるはずですよね?!
ところが、そうじゃないんです!!
上記の動きだと、SheetView2
が消えるときだけ、onSheet1Dismiss
が呼ばれます!
はい、タイポではないです。
SheetView1
が消えるとき、onSheet1Dismiss
呼ばれないし、SheetView2
が消えるとき、onSheet2Dismiss
も呼ばれないです!
これに気づくにはだいぶ時間がかかりました。
調べる時に、他にもonDismiss
にまつわる問題が色々出てきましたが、なかなか上記のケースが見当たりませんでしたのでここに書き残します。
冒頭で書いた通り、この実装自体が微妙かもしれませんが、何かの引っ掛かりになれば嬉しいです。
コメントを残す