Gesture Debug

Capture the gestures your SwiftUI app receives, see which responders handled each one, outline the hit regions inside the running app, and find targets that are too small to tap.

What you need

  • LookInside 3.0 or later
  • LookInsideServer 1.0.0 or later in the Debug build of the app you inspect
  • A SwiftUI app running on iOS or macOS, connected in LookInside
  • For readable event details, the log privacy setting described under Enable readable event details

Older Servers still connect to LookInside 3.0, but Start Capture reports that the target has no gesture-debug capability.

Start a capture

  1. 1

    Connect LookInside to the running app as usual.

  2. 2

    Click Gestures in the inspection window toolbar. The Gesture Debug panel opens next to the inspection.

  3. 3

    Click Start Capture. LookInside asks the Server to turn on SwiftUI event logging in the target process and begins reading the system log.

  4. 4

    Tap, drag, or long press in your app. Each interaction shows up in the Events list on the left.

  5. 5

    Select an event to see its trees, or keep Follow latest on to track the newest one.

  6. 6

    Click Stop Capture when you are done. The Server restores the logging flags it changed and removes its overlays.

What each tab shows

The detail area is split into tabs. The first three and the last two describe the selected event. Native and Suggestions describe the page that is on screen right now, and keep updating while a capture runs.

Responders

The SwiftUI responder tree that handled the selected event, with the view types along the path.

Gestures

Every gesture node SwiftUI evaluated for the event, with the phase it reached.

Bindings

Which responder the event was bound to, so you can see who actually won.

Native

UIKit controls and list rows on the current page, with their target-action, UIAction, or list-selection handlers. These do not need a logged event.

Suggestions

Interaction targets on the current page that are smaller than the platform minimum, with their size and geometry source.

Hit Test

The hit-test records SwiftUI logged for the event, including nested hosting views.

Raw Log

The original log records behind the parsed trees, kept for cases the parser marks incomplete.

Borders in the running app

With Gesture borders on, the Server draws an overlay inside the inspected app that outlines every responder and gesture region it has observed. The region fills briefly when an event binds to it, so you can watch which view wins a tap while you tap it.

Content shapes declared with .contentShape are drawn as their real path for Circle, Ellipse, Capsule, and Rectangle. Shapes whose parameters are not in the log, such as a RoundedRectangle corner radius or a custom path, are drawn as a dashed bounding box instead.

The overlay does not take touches or mouse events, is not part of accessibility, and does not appear in the view hierarchy or in screenshots. On iOS 26 and later the Server also notices when the page changes and clears borders that no longer apply. On older systems use Clear Borders; where the Server can read the current page, the button is Refresh Borders and redraws every region on screen.

Hit target suggestions

The Suggestions tab lists interaction targets on the current page that are smaller than the platform minimum in either dimension. The threshold follows the inspected device, not the Mac running LookInside.

iPhone

44 × 44 pt

Mac, including Mac Catalyst

28 × 28 pt

Each suggestion shows the measured size, the minimum, the view identity, and where the geometry came from. Targets whose bounds are estimated from a native control rather than read from a SwiftUI content shape are marked, so you know when to double-check the number. The warning count also appears in the status line, and matches the border colors drawn in the app.

Enable readable event details

SwiftUI writes gesture events to the unified log with private data redacted. Without the setting below, a capture still records that events happened, but the responder and gesture trees show placeholders instead of names and geometry, and the panel reports the capture as redacted.

Add this to the Debug Info.plist of the app you inspect, then relaunch the app, reconnect, and start a new capture:

<key>OSLogPreferences</key>
<dict>
    <key>com.apple.SwiftUI</key>
    <dict>
        <key>Events</key>
        <dict>
            <key>Enable-Private-Data</key>
            <true/>
        </dict>
    </dict>
    <key>com.apple.diagnostics.events</key>
    <dict>
        <key>SwiftUI</key>
        <dict>
            <key>Enable-Private-Data</key>
            <true/>
        </dict>
    </dict>
</dict>

This only affects the two SwiftUI log categories in your own app. It does not change the system-wide log privacy setting, and it should stay out of release builds like the Server itself.

Export

Export…writes the capture to a JSON file: the event history, parsed trees, the current page's native regions and suggestions, and the raw log records. The export works after a capture has stopped, and also when only native regions were found, so you can attach it to a bug report.

Limits

  • Events come from the system log, which delivers them with a delay of a few hundred milliseconds to a few seconds. The panel is a record of recent interactions, not a live view of the gesture state.
  • Shapes are reconstructed from the logged type and bounds, not read from SwiftUI internals. Rotated or scaled views and nested shapes are approximate.
  • Native regions cover UIKit controls and list rows. AppKit controls and menu-style pickers are not listed yet.
  • Regions that were never touched cannot be enumerated from the log. Native and Suggestions read the current page directly and do not have this limit.