Touch not cancelled on sheet drag
FB18927179: Button touch is not cancelled when sheet drag or scroll gesture starts on a Button inside a ScrollView inside a .sheet
Steps to reproduce:
- Use the attached example snippet: A Button inside a ScrollView inside a .sheet
- Start dragging the sheet or scrolling with the finger on the Button.
Expected behavior: After a little bit of drag movement, it should detect that it’s a scroll/sheet drag and the Button touch should be cancelled / the button action should not be fired. This behaviour can be observed when no ScrollView is present.
Observed behavior: Button touch is not cancelled and the action fires, even when the gesture clearly looked like a sheet drag/scroll.
Discussion: https://developer.apple.com/forums/thread/763436?answerId=849716022#849716022
Workaround:
swift
// » SwiftUI Garden
// » https://swiftui-garden.com/Misc/iOS-26/Touch-not-cancelled-on-sheet-drag
import SwiftUI
public extension View {
// FB18927179: Button touch is not cancelled when sheet drag or scroll gesture starts
// on a Button inside a ScrollView inside a .sheet, bug appeared in iOS 18, adding a
// simultaneous TapGesture prevents the issue. It's enough to stick this once on the
// outer container that is affected.
// Thanks https://mastodon.social/@[email protected]
// https://developer.apple.com/forums/thread/763436?answerId=849716022#849716022
@available(iOS, deprecated: 26.1, message: "Check if this is still needed for iOS 26.1. If it is, bump this deprecation message to a higher version.")
@ViewBuilder
func iOS18ScrollViewButtonTapSheetFix() -> some View {
if #available(iOS 18, *) {
self.simultaneousGesture(TapGesture())
} else {
self
}
}
}
Example code:
swift
// » SwiftUI Garden
// » https://swiftui-garden.com/Misc/iOS-26/Touch-not-cancelled-on-sheet-drag
import SwiftUI
struct TouchNotCancelledOnSheetDragExample: View {
@State var showAlert = false
var body: some View {
Text("Hello, world!")
.sheet(isPresented: .constant(true)) {
NavigationStack {
ScrollView(.vertical) {
VStack {
ForEach(1 ... 100, id: \.self) { _ in
Button("Hello World") {
self.showAlert = true
}
}
}
.frame(maxWidth: .infinity)
.buttonStyle(.borderedProminent)
// Workaround: .iOS18ScrollViewButtonTapSheetFix()
}
.alert(isPresented: $showAlert) {
Alert(title: Text("Button tapped"))
}
.navigationTitle("Scrollable view in sheet")
.navigationBarTitleDisplayMode(.inline)
}
}
}
}
#Preview {
TouchNotCancelledOnSheetDragExample()
}