TechnologiesSwiftUIPreviews and Layout Modifiers

PreviewContextKey protocol

iOSmacOStvOSwatchOSvisionOSiOS 14.0+✓ renders

A key type for a preview context.

How it works

PreviewContextKey is the protocol you adopt to declare a typed slot in a preview's context — the bag of values that Xcode's preview machinery carries alongside your view while it renders in the canvas. By conforming a key type to PreviewContextKey and supplying a defaultValue, you give that slot a stable identity and a fallback, so any view can read the value out of a PreviewContext even when no one has set it. Reach for it when you want preview-only configuration — a device scale, a layout hint, a simulated environment fact — to flow through previews in the same key-based way that EnvironmentKey and PreferenceKey move values through the live view hierarchy.

  1. Conform a key type to PreviewContextKey

    Each distinct value you want to read from a preview context needs its own conforming type, usually a small nested struct whose type identity is the key. Here DeviceScaleKey is declared struct DeviceScaleKey: PreviewContextKey, which is all that's required to mint a new slot — the type itself, not an instance, names the value.

  2. Supply the required defaultValue

    The protocol's one requirement is a static defaultValue, returned whenever a context hasn't been given an explicit value for the key. Its type also fixes the type of everything stored under the key: static var defaultValue: Double = 1.0 makes DeviceScaleKey a Double-valued slot that falls back to 1.0.

  3. Read the value through the key's static member

    Because the value lives behind the type, you access it via the key rather than an instance — the same pattern as EnvironmentKey. The body reads DeviceScaleKey.defaultValue straight into the interpolated Text("Default scale: \(DeviceScaleKey.defaultValue, specifier: "%.1f")"), showing the fallback the context will hand back when the key is unset.

  4. Keep keys scoped and preview-only

    Keys are typically nested inside the view or preview that uses them, as DeviceScaleKey is nested in PreviewContextKeyDemo, so the slot stays private to the code that understands it. Conformances cost nothing at runtime and only matter while the preview context is alive, which is why PreviewContextKey is the right tool for canvas-time configuration rather than shipping app state.

Try it — Change static var defaultValue: Double = 1.0 to 2.0 and watch the Text("Default scale: ...") line update to 2.0, confirming that the displayed value comes from the key's defaultValue.

Example & preview

Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.

PreviewContextKey.swift
struct PreviewContextKeyDemo: View {
    struct DeviceScaleKey: PreviewContextKey {
        static var defaultValue: Double = 1.0
    }

    var body: some View {
        VStack(spacing: 8) {
            Text("PreviewContextKey")
                .font(.headline)
            Text("Default scale: \(DeviceScaleKey.defaultValue, specifier: "%.1f")")
                .font(.subheadline)
                .foregroundStyle(.secondary)
        }
        .padding()
    }
}
Live preview
PreviewContextKey Default scale: {DeviceScaleKey.defaultValue, specifier: "%.1f"}
PreviewContextKey Default scale: {DeviceScaleKey.defaultValue, specifier: "%.1f"}
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →