View Hierarchy for iOS

Learn more about debugging the view hierarchy when an error occurs. Sentry pairs the view hierarchy representation with the original event, giving you additional insight into issues.

Sentry makes it possible to render a JSON representation of the view hierarchy of an error and includes it as an attachment.

This feature only applies to SDKs with a user interface, such as the ones for mobile and desktop applications. In some environments like native iOS, rendering the view hierarchy requires the UI thread and in the event of a crash, that might not be available. Another example where the view hierarchy might not be available is when the event happens before the screen starts to load. So inherently, this feature is a best effort solution.

View hierarchy debugging is an opt-in feature. You can enable it as shown below:

Copied
import Sentry

SentrySDK.start { options in
  options.attachViewHierarchy = true
}

The beforeCaptureViewHierarchy also allows you to customize the behavior based on event data, so you can decide when to capture a view hierarchy and when not to. The callback doesn't work for crash events.

Copied
import Sentry

SentrySDK.start { options in
    options.dsn = "___PUBLIC_DSN___"
    options.beforeCaptureViewHierarchy = { _ in
        // Return false to not capture a view hierarchy for the event.
        return false
    }
}

Sentry doesn't collect any user information (such as UILabel and UITextView text) with the view hierarchy attachment, which only contains structure and properties.

If you're using the view's accessibilityIdentifier property with personal information, make sure to disable accessibilityIdentifier reporting like in the example below:

Copied
import Sentry
SentrySDK.start { options in
  options.attachViewHierarchy = true
  options.reportAccessibilityIdentifier = false
}

The SDK stores the hierarchy in a view-hierarchy.json attachment. The attachment uses the application/json content type and the event.view_hierarchy attachment type so Sentry can render it as an interactive hierarchy.

The following example contains one window, its view controller's root view, and a child view:

view-hierarchy.json
Copied
{
  "rendering_system": "UIKIT",
  "windows": [
    {
      "type": "UIWindow",
      "identifier": "main-window",
      "width": 390,
      "height": 844,
      "x": 0,
      "y": 0,
      "alpha": 1,
      "visible": true,
      "children": [
        {
          "type": "UIView",
          "view_controller": "CheckoutViewController",
          "width": 390,
          "height": 844,
          "x": 0,
          "y": 0,
          "alpha": 1,
          "visible": true,
          "children": [
            {
              "type": "UIButton",
              "identifier": "submit-order",
              "width": 200,
              "height": 44,
              "x": 95,
              "y": 720,
              "alpha": 1,
              "visible": true,
              "children": []
            }
          ]
        }
      ]
    }
  ]
}

The root object contains these fields:

FieldTypeDescription
rendering_systemstringRendering system that produced the hierarchy. The Apple SDK uses UIKIT.
windowsarrayTop-level window nodes. Each window uses the same recursive node structure as its descendants.

Each window or child node, except truncation markers, contains these fields:

FieldTypeRequiredDescription
typestringYesRuntime class name of the view, such as UIWindow, UIView, or UIButton.
widthnumberYesWidth of the view's frame in points.
heightnumberYesHeight of the view's frame in points.
xnumberYesHorizontal origin of the view's frame in its containing coordinate space, in points.
ynumberYesVertical origin of the view's frame in its containing coordinate space, in points.
alphanumberYesOpacity of the view, from 0 for transparent to 1 for opaque.
visiblebooleanYesWhether the view's isHidden property is false. This does not account for the visibility or alpha of ancestor views.
childrenarrayYesChild views in UIKit subview order. An empty array indicates that the node has no child views.
identifierstringNoThe view's accessibilityIdentifier. The SDK omits this field when the identifier is empty or reportAccessibilityIdentifier is disabled.
view_controllerstringNoRuntime class name of the view controller when this node is the controller's root view.

To keep captures bounded, the Apple SDK records up to 90 levels of nested views. When a view at that limit has child views, the SDK replaces those child views with a truncation marker:

Copied
{
  "type": "SentryTruncatedViewHierarchy"
}

Truncation markers contain only the type field. The other required fields in the table above do not apply to these markers.

View hierarchies appear in the "Attachments" tab, where you can view all attachments, as well as associated events. Click the event ID to open the Issue Details page of that specific event.

On the Issue Details page, you can interact with the view hierarchy attachment in a section called "View Hierarchy". This section represents the state of your application at the time of an error event. There are three displays: a tree view, wireframe, and detailed view for a selected node. Select a node in the tree or wireframe to inspect its JSON fields. Use these displays to debug layout issues, find unnecessarily rendered content, or understand the relationship between views.

Was this helpful?
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").