Lab 075 – Visualizing SwiftUI Frames

Using an incredibly useful view extension from WWDC 2025 to debug and visualize spatial layouts.

Overview

One of my favorite visionOS sessions from WWDC 2025 is Meet SwiftUI spatial layout. If you haven’t seen it yet, do yourself a favor and go watch it. This session introduced several new features in SwiftUI for making our window and volume content a bit more spatial. The focus here is on SwiftUI views like custom layouts, Model3D, overlays etc.

We’ve created Example Code for the most useful new concepts in the Spatial SwiftUI series.

If you’ve seen any of those examples you may have noticed the debug border around views.

Debug border from the spatialOverlay example

These lines are useful for debugging and visualizing the exact size and shape of view frames. This is particularly useful when working with Z depth or building spatial layouts. At the end of the WWDC session, the presenter shared an extension for creating these. It is called debugBorder3D and is an extension of View.

/// See WWDC 2025 Session: Meet SwiftUI spatial layout
/// https://developer.apple.com/videos/play/wwdc2025/273
extension View {
    func debugBorder3D(_ color: Color) -> some View {
        spatialOverlay {
            ZStack {
                Color.clear.border(color, width: 4)
                ZStack {
                    Color.clear.border(color, width: 4)
                    Spacer()
                    Color.clear.border(color, width: 4)
                }
                .rotation3DLayout(.degrees(90), axis: .y)
                Color.clear.border(color, width: 4)
            }
        }
    }
}

It’s notable that this relies on three new features introduced during the session. They used the new features to build a debug helper that is useful when using the new features. You gotta love that!

  • rotation3DLayout impacts the layout and frame of a view (unlike rotation3DEffect, which is a visual effect only).
  • spatialOverlay allows us to over SwiftUI views on other views, with some sensible alignments.
  • Spatial Container (relied upon my spatialOverlay allows multiple views to exist in the same space.

I found this so useful that I’ve added it to all my projects. This lab is here to encourage you to do the same. Add this to your toolbox and reach for it when you need it.

Let’s see a few ways to use this. Here we have a Window with a top level HStackLayout. On the left we have some flat SwiftUI views (offset to create some depth. On the right we have a VStackLayout with some 3D Models.

We’re using debugBorder3D several times here.

  • black box: the outer HStackLayout with some padding
  • white boxes: container views
    • VStack for the three rounded rects
    • VStackLayout for the 3D Models
  • red, green, and blue boxes: Model3D view with spatialOverlay

You can add this to any view at any level of the hierarchy. It can be useful for checking alignment, visualizing the space between views of varying size and shape, getting finding the edge or a view or window.

Video Demo

Full Lab Code

struct Lab075: View {
    var body: some View {
        HStackLayout(spacing: 12).depthAlignment(.center) {

            VStack(spacing: 8) {
                RoundedRectangle(cornerRadius: 8)
                    .fill(.stepRed)
                    .offset(z: -25)
                RoundedRectangle(cornerRadius: 8)
                    .fill(.stepGreen)
                RoundedRectangle(cornerRadius: 8)
                    .fill(.stepBlue)
                    .offset(z: 25)
            }
            .frame(width: 200, height: 300)
            .frame(depth: 50)
            .debugBorder3D(.white)

            VStackLayout(spacing: 8).depthAlignment(.center) {
                ModelViewSimple(name: "ToyRocket", bundle: realityKitContentBundle)
                    .frame(width: 100, height: 100)
                    .debugBorder3D(.stepRed)
                    .spatialOverlay(alignment: .bottomFront, content: {
                        Text("Toy Rocket")
                            .font(.caption)
                            .padding(8)
                            .background(.black)
                            .clipShape(.capsule)
                    })

                ModelViewSimple(name: "ToyCar", bundle: realityKitContentBundle)
                    .frame(width: 100, height: 100)
                    .debugBorder3D(.stepGreen)
                    .spatialOverlay(alignment: .bottomFront, content: {
                        Text("Toy Car")
                            .font(.caption)
                            .padding(8)
                            .background(.black)
                            .clipShape(.capsule)
                    })

                ModelViewSimple(name: "ToyBiplane", bundle: realityKitContentBundle)
                    .frame(width: 100, height: 100)
                    .debugBorder3D(.stepBlue)
                    .spatialOverlay(alignment: .bottomFront, content: {
                        Text("Toy Biplane")
                            .font(.caption)
                            .padding(8)
                            .background(.black)
                            .clipShape(.capsule)
                    })
            }
            .padding()
            .debugBorder3D(.white)

        }
        .padding()
        .debugBorder3D(.black)
    }
}

Download the Xcode project with this and many more labs from Step Into Vision.

Questions or feedback?