I noticed if I show a sheet from a List
row, then remove the row the sheet isn't removed from the screen like it is if using VStack
or LazyVStack
.
I'd be interested to know the reason why the sheet isn't removed from the screen in the code below. It only occurs with List
/Form
. VStack
/LazyVStack
gives the expected result. I was wondering if it is an implementation issue, e.g. since List is backed by UICollectionView
maybe the cells can't be the presenter of the sheet for some reason.
- Launch on iPhone 16 Pro Simulator iOS 18.2
- Tap "Show Button"
- Tap "Show Sheet"
What is expected:
The sheet should disappear after 5 seconds. And I don't mean it should dismiss, I just mean removed from the screen. Similarly if the View that showed the sheet was re-added and its show @State
was still true, then the sheet would be added back to the screen instantly without presentation animation.
What actually happens: Sheet remains on screen despite the row that presented the sheet being removed.
Xcode 16.2 iOS Simulator 18.2.
struct ContentView: View {
@State var showButton = false
var body: some View {
Button("\(showButton ? "Hide" : "Show" ) Button") {
showButton = true
Task {
try? await Task.sleep(for: .seconds(5))
self.showButton = false
}
}
//LazyVStack { // does not have this problem
List {
if showButton {
SheetButton()
}
}
}
}
struct SheetButton: View {
@State var sheet = false
@State var counter = 0
var body: some View {
Text(counter, format: .number)
Button("\(sheet ? "Hide" : "Show") Sheet") {
counter += 1
sheet.toggle()
}
.sheet(isPresented: $sheet) {
Text("Wait... This should auto-hide in 5 secs. Does not with List but does with LazyVStack.")
Button("Hide") {
sheet = false
}
.presentationDetents([.fraction(0.3)])
}
// .onDisappear { sheet = false } // workaround
}
}
I can work around the problem with .onDisappear { sheet = false }
but I would prefer the behaviour to be consistent across the container controls.