[SwiftUI] sheetのonDismissの変な挙動

投稿日:

更新日:

カテゴリ:

sheetのonDismissの変な挙動ですが、そもそも実装自体が変かもしれません。

ソースは以下です。

ContentViewからsheetSheetView1を呼び出せるボタンを入れます。

SheetView1中に自分を閉じるボタンとSheetView2の表示フラグを変えて自分が消えるボタンを入れます。

ContentViewに設定されているSheetView2は表示更新フラグに従ってSheetView2を表示するようにします。

SheetView1SheetView2にはそれぞれの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()
}

挙動の確認だけですので、画面はシンプルでこんな感じです。

さてと、ここからが問題です。

SheetView1Open View 2ボタンを押してSheetView2を開き、SheetView2Closeボタン押したらContentViewに戻りますが、onDismissに設定された関数はどのように呼び出されるでしょうか?

読み通りに行くと、SheetView2を開く時に、SheetView1は自分が消えますので、ここでがonSheet1Dismiss呼ばれ、SheetView2Closeボタン押した時に、SheetView2も消えますので、ここでがonSheet2Dismiss呼ばれるはずですよね?!

ところが、そうじゃないんです!!

上記の動きだと、SheetView2が消えるときだけ、onSheet1Dismissが呼ばれます!

はい、タイポではないです。

SheetView1が消えるとき、onSheet1Dismiss呼ばれないし、SheetView2が消えるとき、onSheet2Dismissも呼ばれないです!

 

これに気づくにはだいぶ時間がかかりました。

調べる時に、他にもonDismissにまつわる問題が色々出てきましたが、なかなか上記のケースが見当たりませんでしたのでここに書き残します。

冒頭で書いた通り、この実装自体が微妙かもしれませんが、何かの引っ掛かりになれば嬉しいです。


投稿日

カテゴリー:

投稿者:

タグ:

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です