Skip to content

Preview Macro (SwiftUI)

A SwiftUI guide for coding agents. Also covers preview macro xcode, hashtag preview swift, xcode canvas previews, preview traits landscape, uikit view controller preview, widget timeline preview, and 2 more.

Show all 8 aliases

preview macro xcode, hashtag preview swift, xcode canvas previews, preview traits landscape, uikit view controller preview, widget timeline preview, dynamic type preview, debug preview process

The #Preview macro renders a view in the Xcode Preview Canvas with one closure, replacing the PreviewProvider boilerplate. It also previews UIKit types and widget timelines.

The Basic Form

Wrap the view in the macro. Any modifier applies, so a dark-mode preview is one line.

#Preview {
  ContentView()
    .preferredColorScheme(.dark)
}

The macro is not SwiftUI-only. Return any UIViewController or UIView instance and the canvas renders it too.

#Preview {
  SearchViewController()
}

One Preview Per State

Declare several #Preview macros in one file to show different states side by side. Pass a title string so the canvas can tell them apart.

#Preview("Empty state") {
  ItemsView(data: .empty)
}

#Preview("Error state") {
  ItemsView(data: .error)
}

A file can contain only previews. That works well as living documentation for a design system package: one file per component, one preview per state.

Traits: Orientation and Size

The traits parameter puts the preview in landscape or a fixed layout size. This overload is iOS 17+, so it needs an availability attribute in code that targets earlier versions.

@available(iOS 17, *)
#Preview(traits: .landscapeLeft) {
  ContentView()
}

@available(iOS 17, *)
#Preview(traits: .fixedLayout(width: 300, height: 300)) {
  ContentView()
}

Sweep a Whole Axis

A wrapper view previews every variant of one environment axis at once, such as every Dynamic Type size.

struct SizeCategoryPreview<Content: View>: View {
  let content: Content

  var body: some View {
    ForEach(ContentSizeCategory.allCases, id: \.self) { size in
      content.environment(\.sizeCategory, size)
    }
  }
}

#Preview {
  SizeCategoryPreview(content: ContentView())
}

Debugging a Preview

Previews run in an embedded simulator, so you can debug them: Debug menu, Attach to Process, pick the app, then use Debug View Hierarchy. Cmd+Option+Enter toggles the canvas and Cmd+Option+P runs the preview. Small, decomposed views keep previews fast and stable.

Widget Timelines

The as: overload previews a widget in a given family and plays an interactive timeline from the provider you supply.

#Preview(as: .accessoryRectangular) {
  SugarBotWidget()
} timeline: {
  RawValuesProvider()
}

Use this guidance in your coding agent

Install the Better Design MCP once. Your agent then loads this page with one call.

get-swiftui-guide({ topic: "swiftui-mastering-preview-macro-in-swift" })
claude mcp add --scope user better-design --transport http https://better-design.com/api/mcp --header "Authorization: Bearer <YOUR_API_KEY>"
Browse related design systems