Description
Tapping a view with .onTapGesture can abort an iOS app when gesture debugging is enabled with _eventDebugTriggers = .all. The crash occurs when a layout gesture resets a terminal child and evaluates its debug data.
Reproduction
Run the OpenSwiftUI iOS example with this ContentView, then tap "Hello, world!":
import OpenSwiftUI
struct ContentView: View {
init() {
_eventDebugTriggers = .all
}
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
.onTapGesture {
print("A")
}
Color.red
.onTapGesture {
print("B")
}
}
.padding()
}
}
Expected behavior
The tap completes, and gesture debug data remains available without a crash.
Actual behavior
The app aborts with a Swift exclusivity violation:
Simultaneous accesses to 0x6000037182e0, but modification requires exclusive access.
Previous access (a modification) started at OpenSwiftUICore`LayoutGestureBox.resetTerminalChildren<A>(gesture:) + 916 (0x107665884).
Current access (a read) started at:
0 libswiftCore.dylib swift::runtime::AccessSet::insert
1 libswiftCore.dylib swift_beginAccess
2 OpenSwiftUICore LayoutChildSeed.value.getter + 140
3 OpenSwiftUICore protocol witness for Rule.value.getter in conformance LayoutChildSeed<A> + 48
4 AttributeGraph __swift_memcpy56_8
Cause and scope
children[index].reset() holds a modifying access to the children array. During the reset, reading lazy gesture debug data can make AttributeGraph evaluate LayoutChildSeed.value, which reads the same array and causes the conflict. The same reset pattern is used for terminal children, reset-seed changes, and child removal.
The terminal-reset conflict also reproduces with system SwiftUI on the iOS 18.5 Simulator when SWIFTUI_GESTURE_CONTAINER=0 and gesture debugging is enabled.
Description
Tapping a view with
.onTapGesturecan abort an iOS app when gesture debugging is enabled with_eventDebugTriggers = .all. The crash occurs when a layout gesture resets a terminal child and evaluates its debug data.Reproduction
Run the OpenSwiftUI iOS example with this
ContentView, then tap "Hello, world!":Expected behavior
The tap completes, and gesture debug data remains available without a crash.
Actual behavior
The app aborts with a Swift exclusivity violation:
Cause and scope
children[index].reset()holds a modifying access to the children array. During the reset, reading lazy gesture debug data can make AttributeGraph evaluateLayoutChildSeed.value, which reads the same array and causes the conflict. The same reset pattern is used for terminal children, reset-seed changes, and child removal.The terminal-reset conflict also reproduces with system SwiftUI on the iOS 18.5 Simulator when
SWIFTUI_GESTURE_CONTAINER=0and gesture debugging is enabled.