In this post, we will explore potential fixes for the issue where SwiftUI List
elements fail to register onTapGesture
actions after upgrading to iOS 18. The code worked perfectly fine over the past few months but now behaves inconsistently on iPhones running iOS 18. While holding down a button or element triggers the tapGesture
action as expected, a quick tap often does not. Occasionally, the onTapGesture
is recognized, but it is not reliable.
I encountered an issue where a button inside a List
and its onTapGesture
stopped responding after upgrading to iOS 18. After researching the problem, I discovered that if a parent view has a TapGesture
applied, it can override the TapGesture
of its child views. To address this, there are a few solutions available. Let’s explore them.
Adding highPriority TapGesture
We can resolve this issue by adding a high-priority TapGesture
to the child view. This method works effectively if the child view has only a single TapGesture
applied.
.highPriorityGesture( TapGesture().onEnded { _ in // your code here to handle tap gesture...... } )
Replace parentView’s .onTapGesture
with .simultaneousGesture
In my case, I had both a button and a TapGesture
on the child view, while the parent view also had a TapGesture
to dismiss the keyboard. Using a high-priority TapGesture
was not a viable solution because it overrode the previously applied TapGesture
actions, causing all button links to trigger the action defined in the last TapGesture
. Instead, I used simultaneousGesture
and applied it to the parent view. Below is an example:
let newGesture = TapGesture().onEnded { UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) } var body: some View { VStack(spacing:25) { Text("Child view goes here") Rectangle() .fill(Color.blue) } .simultaneousGesture(newGesture) .frame(width: 200, height: 200) .border(Color.purple) } }