SwiftUI isPresented Environment not updated for sheet dismissed

Viewed 190

Given the following minimal reproducible example:

struct ParentView: View {
  @State private var showSheet = false
  
  var body: some View {
    return Button("Show sheet") {
      showSheet.toggle()
    }.sheet(
      isPresented: $showSheet,
      onDismiss: {
        print("Parent onDismiss")
      },
      content: {
        NavigationView {
          SheetView(parentShowSheet: $showSheet)
        }
      }
    )
  }
}

struct SheetView: View {
  @Environment(\.dismiss) private var dismiss
  @Environment(\.isPresented) private var isPresented
  @Binding var parentShowSheet: Bool
  
  var body: some View {
    Button("Manual close") {
      dismiss()
    }
    .onChange(of: isPresented) { isPresented in
      print("Sheet isPresented", isPresented)
    }
    .onChange(of: parentShowSheet) { parentShowSheet in
      print("Sheet parentShowSheet", parentShowSheet)
    }
  }
}

The SheetView's onChange methods are not triggering in the way I would expect. In this example there are two ways to close a sheet once it's opened :

  1. Click the "Manual close" button which triggers dismiss(), or
  2. Pull down the sheet to trigger an "interactive close" (the thing that is disabled when .interactiveDismissDisabled(true) is added to the view).

If you try these both out you'll see that for (1) you'll get two print statements "Sheet parentShowSheet" and "Parent onDismiss", while for (2) you'll just get one print statement "Parent onDimiss".

Three questions:

  • Why does "Sheet parentShowSheet" not print in case (2)?
  • Why does "Sheet isPresented" not print in either case? I'd think that dismissing a sheet is very literally changing it's Environment(\.isPresented) value.
  • How can I add a hook inside of the SheetView that triggers when it is dismissed with either method (1) or method (2) (e.g. something that operates like either of my onChange methods, but actually works in both cases)?
0 Answers
Related