---
title: "Debugging Techniques"
description: "How to Debug SwiftUI Layout"
url: https://www.swiftuifieldguide.com/layout/debugging
markdown_url: https://www.swiftuifieldguide.com/layout/debugging.md
---
> Convenience Markdown export of the HTML page. Interactive samples, diagrams, and visualizations stay on the canonical page.
# Debugging Techniques

One of the most useful debugging techniques in SwiftUI is to add a border to a view. Because a border (under the hood) is just an overlay with a stroked rectangle, it shows the exact size and position of the view it is applied to. We use this technique throughout the entire site. For example, adding a border to the example from the [introduction](/layout/introduction) visualizes the padding:

> Pretty-printed code from Border

```swift
Text("Hello, World!")
    .background(Color.accentColor)
    .padding()
    .border(.red)
```

> Interactive example on HTML page: Border.

Another very useful debugging technique is to use [`GeometryReader`](/layout/geometry-reader) to visualize the size of a view. Again, by putting the geometry reader in an overlay we can see the exact size without changing the layout behavior of the underlying view. Note that we can do this in just a few lines, but we added some extra code to make things look nice.

> Pretty-printed code from Sample GR

```swift
Text("Hello, world. This is a longer text.")
    .overlay {
        GeometryReader { proxy in
            Text(
                "\(proxy.size.width) x \(proxy.size.height)"
            )
                .font(.caption)
                .foregroundStyle(.white)
                .padding(4)
                .background(.purple)
                .fixedSize()
                .frame(width: proxy.size.width,
                       height: proxy.size.height)
        }
    }
```

> Interactive example on HTML page: Sample GR.

In general, it can be helpful to add an overlay to a view with debug information. This is often easier to parse than when the information is logged to the console, because we see it directly inside our view.

When creating a new view, we often create a new throwaway Xcode project that also includes a Mac target. Because a Mac window is resizable, it quickly helps us debug the resizing behavior of our views. Alternatively, we can put a slider in the preview (or in the view) that lets us control the width of a view. For debugging different color schemes, size categories and orientation, the builtin previews are great.

It can also be helpful to add specific overlays to views. For example, to visualize the value of an [alignment guide](/layout/alignment), we can add a 1pt tall red rectangle in an overlay:

> Pretty-printed code from Sample Alignment Guide

```swift
Text("Hello, world")
    .font(.largeTitle)
    .overlay(
        alignment: .centerFirstTextBaseline
    ) {
        Color.red
            .frame(height: 1)
    }
    .padding(30)
```

> Interactive example on HTML page: Sample Alignment Guide.

## Logging Proposing and Reporting {#logging}

To understand the process of proposing and reporting, we can use a custom [layout](/layout/layout) that logs the proposed and reported sizes.

> Pretty-printed code from Custom Layout Code

```swift
struct DebugLayout: Layout {
    let name: String

    func sizeThatFits(proposal: ProposedViewSize,
                      subviews: Subviews,
                      cache: inout ()) -> CGSize {
        let result =
            subviews[0].sizeThatFits(proposal)
        print(name, proposal, result)
        return result
    }
    
    func placeSubviews(in bounds: CGRect,
                       proposal: ProposedViewSize,
                       subviews: Subviews,
                       cache: inout ()) {
        subviews[0].place(at: bounds.origin,
                          proposal: proposal)
    }
}

extension View {
    func debugLog(_ name: String) -> some View {
        DebugLayout(name: name) { self }
    }
}
```

> Interactive example on HTML page: Custom Layout Code.

Using the above code, we can add `.debugLog` to any view and see exactly what is proposed and reported. For example, if we add this to the each of the subviews of an HStack, we can see how the HStack is first probing the children for their flexibility by proposing both a zero and an infinite width, and then proposing in order of flexibility.
