BS
BleepingSwift
Published on
5 min read

> Debugging SwiftUI Previews in Xcode

Authors
  • avatar
    Name
    Mick MacCallum
    Twitter
    @0x7fs

SwiftUI previews save a lot of time when they're working. When they're not, the canvas shows a cryptic error and the diagnostics panel dumps a wall of compiler output that's hard to parse. Over time I've built up a set of techniques for tracking down what's actually wrong, from quick cache clears to digging through preview logs.

Start with the Diagnostics Panel

When a preview fails, the canvas shows a "Diagnostics" button. Click it, then scroll to the bottom of the output. The actual error is usually buried under dozens of compilation commands. What you're looking for is the final error message or crash log.

If the error mentions a specific file and line number, the fix is usually straightforward. But if it's something vague like "Cannot preview in this file," the problem is often somewhere else in your project entirely. In that case, try building the project with Cmd+B first. Preview failures frequently stem from build errors in unrelated files that haven't surfaced yet.

Clearing the Preview Cache

Previews use their own simulator environment under the hood, and that environment can get into a bad state. When you've tried the obvious fixes (cleaning the build folder with Shift+Cmd+K, resuming with Option+Cmd+P) and previews still won't load, it's time to clear the preview cache directly.

Run this in Terminal:

xcrun simctl --set previews delete all

This deletes all preview simulator devices that Xcode has created. The next time you open a preview, Xcode creates fresh ones. This is particularly useful when previews fail with runtime errors that don't match your code, or when you see errors about the preview process crashing before it could produce output.

Deleting Derived Data

If clearing the preview cache doesn't help, stale build artifacts might be the problem. Xcode stores all intermediate build products in the DerivedData folder, and corruption here causes a surprising number of preview failures.

You can delete your project's derived data through Xcode by going to Settings > Locations and clicking the arrow next to the DerivedData path, then finding and deleting your project's folder. Or you can clear everything from the command line:

rm -rf ~/Library/Developer/Xcode/DerivedData

After deleting derived data, build your project again before trying to resume previews. Previews depend on a successful build, so giving Xcode a clean build to work from eliminates a whole class of stale-cache issues.

Using Print Statements in Previews

One underused debugging technique is adding print() calls to your preview code. Preview output goes to Xcode's console, but only if you enable it. Go to Editor > Canvas > Preview Output to open the preview console panel.

This is useful when your preview compiles but shows unexpected content. You can print values to verify that your mock data is correct or that a computed property returns what you expect:

struct WeatherCard: View {
    let temperature: Double

    var formattedTemperature: String {
        let result = String(format: "%.0f°", temperature)
        print("Formatted temperature: \(result)")
        return result
    }

    var body: some View {
        Text(formattedTemperature)
            .font(.largeTitle)
    }
}

#Preview {
    WeatherCard(temperature: 72.6)
}

That works in computed properties and regular functions, but print() won't compile inside body directly because SwiftUI's @ViewBuilder expects view expressions, not statements. The workaround is let _ = print(...), which the compiler treats as a valid expression inside a view builder:

var body: some View {
    let _ = print("Body evaluated, temperature: \(temperature)")
    VStack {
        Text(formattedTemperature)
            .font(.largeTitle)
    }
}

This is handy for checking how often a view's body is being re-evaluated, or for verifying that the values flowing into your view are what you expect. Just remember to remove these before shipping.

Attaching the Debugger to a Preview

For trickier issues, you can set breakpoints and debug previews just like a running app. Click the "Debug Preview" button at the bottom of the canvas (or use the menu at Editor > Canvas > Debug Preview). This launches the preview with the debugger attached, so your breakpoints will fire and you can inspect state.

This is especially helpful when a preview renders but shows wrong data. Instead of scattering print statements everywhere, set a breakpoint, inspect the variables, and step through the rendering logic.

Checking the Preview Crash Logs

When previews crash immediately with no useful diagnostic output, the crash logs can tell you what happened. Preview crashes get written to ~/Library/Logs/DiagnosticReports/. Look for files with "Preview" or "XCPreviewAgent" in the name.

You can also check the system log for preview-related messages:

log show --predicate 'subsystem == "com.apple.dt.preview"' --last 5m

This filters the last five minutes of system logs for preview subsystem messages. If a preview is crashing due to a missing framework, a sandbox violation, or a signing issue, the details usually show up here.

When All Else Fails

If you've cleared the preview cache, deleted derived data, and still can't get previews working, try these in order:

Quit Xcode completely and reopen your project. The preview service can get wedged in ways that persist until Xcode restarts.

Delete the Xcode caches directory at ~/Library/Caches/com.apple.dt.Xcode in addition to derived data. This covers caches that derived data deletion alone doesn't touch.

Restart your Mac. Some preview service processes survive even a full Xcode restart, and a reboot clears them out.

If none of that works, you likely have a code issue rather than a caching one. Try creating a minimal #Preview block with a simple Text("Hello") view. If that renders, the problem is in your view's code. If even a basic preview fails, the issue is at the project or environment level and you should check that your scheme is targeting a valid simulator and that all your project's dependencies build cleanly.

Sample Project

Want to see this code in action? Check out the complete sample project on GitHub:

View on GitHub

The repository includes a working Xcode project with all the examples from this article, plus unit tests you can run to verify the behavior.

subscribe.sh

// Stay Updated

Get notified when I publish new tutorials on Swift, SwiftUI, and iOS development. No spam, unsubscribe anytime.

>

By subscribing, you agree to our Privacy Policy.