I’ve been investigating a noticeable animation hitch when interactively dismissing a sheet over a SwiftUI screen with moderate complexity. This was not the case on iOS 18, so I’m curious if others are seeing the same on iOS 26 or have found any mitigations.
When dismissing a sheet via the swipe gesture, there’s a visible hitch right after lift-off.
- The hitch comes from layout work in the underlying view (behind the sheet)
- The duration scales with the complexity of that view (e.g. number of TextFields/layout nodes)
The animation for programmatic dismiss (e.g. tapping a “Done” button) is smooth, although it hangs for a similar amount of time before dismissing, so it appears that the underlying work still happens.
SwiftUI is not reevaluating the body during this (validated with Self._printChanges()), so that is not the cause.
Using Instruments, the hitch shows up as a layout spike on the main thread:
54ms UIView layoutSublayersOfLayer
54ms └─ _UIHostingView.layoutSubviews
38ms └─ SwiftUI.ViewGraph.updateOutputs
11ms ├─ partial apply for implicit closure #1 in closure #1
│ in closure #1 in Attribute.init<A>(_:)
4ms └─ -[UIView
For the same hierarchy with varying complexity:
- ~3 TextFields in a List: ~25ms (not noticeable)
- ~20+ TextFields: ~60ms (clearly visible hitch)
The same view hierarchy on iOS 18 did not exhibit a visible hitch. I’ve tested this on an iOS 26.4 device and simulator.
I’ve also included a minimum reproducible example that illustrates this:
struct ContentView: View {
@State var showSheet = false
var body: some View {
NavigationStack {
ScrollView {
ForEach(0..<120) { _ in
RowView()
}
}
.navigationTitle("Repro")
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button("Present") {
showSheet = true
}
}
}
.sheet(isPresented: $showSheet) {
PresentedSheet()
}
}
}
}
struct RowView: View {
@State var first = ""
@State var second = ""
var body: some View {
VStack(alignment: .leading, spacing: 12) {
Text("Row")
.font(.headline)
HStack(spacing: 12) {
TextField("First", text: $first)
.textFieldStyle(.roundedBorder)
TextField("Second", text: $second)
.textFieldStyle(.roundedBorder)
}
HStack(spacing: 12) {
Text("Third")
Text("Fourth")
Image(systemName: "chevron.right")
}
}
}
}
struct PresentedSheet: View {
@Environment(\.dismiss) private var dismiss
var body: some View {
NavigationStack {
List {}
.navigationTitle("Swipe To Dismiss Me")
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button("Done") {
dismiss()
}
}
}
}
}
}
Is anyone else experiencing this and have any mitigations been found beyond reducing view complexity?
I’ve filed a feedback report under FB22501630.