Neil Macy

Previews in Xcode Playgrounds

In a project I'm currently working on, our SwiftUI Previews are broken. But rather than running the app every time I want to work on developing a view, I've been doing initial development in Xcode Playgrounds, which can also run previews.

It's really easy to set up:

import PlaygroundSupport
import SwiftUI

struct MyView: View {
    // your view here
}

let view = MyView()
PlaygroundPage.current.setLiveView(view)

For example, I want to experiment with different Toggle styles in SwiftUI. I've copied these examples from Apple's documentation for Toggle and ToggleStyle, and I can then see how they look, and tweak different properties. And it's interactive, so when I interact with one of my Toggles, it changes the state.

A screenshot showing Xcode Playgrounds running a live SwiftUI Preview.

Here's my code for the Toggles (again, all taken from Apple's documentation):

import PlaygroundSupport
import SwiftUI

struct Toggles: View {
    @State private var vibrateOnRing = false

    var body: some View {
        VStack(spacing: 16) {
            Toggle("Vibrate on Ring", isOn: $vibrateOnRing)

            Toggle(
                "Vibrate on Ring",
                systemImage: "dot.radiowaves.left.and.right",
                isOn: $vibrateOnRing
            )

            Toggle("Vibrate on Ring", isOn: $vibrateOnRing)
            .toggleStyle(.button)

            Toggle(isOn: $vibrateOnRing) {
                Text("Vibrate on Ring")
                Text("Enable vibration when the phone rings")
            }
            .toggleStyle(.switch)

            Toggle(isOn: $vibrateOnRing) {
                Text("Vibrate on Ring")
                Text("Enable vibration when the phone rings")
            }
            .toggleStyle(ChecklistToggleStyle())
        }
        .padding()
    }
}

struct ChecklistToggleStyle: ToggleStyle {
    func makeBody(configuration: Configuration) -> some View {
        Button {
            configuration.isOn.toggle()
        } label: {
            HStack {
                Image(systemName: configuration.isOn
                        ? "checkmark.circle.fill"
                        : "circle")
                .tint(.green)
                configuration.label
            }
        }
        .tint(.primary)
        .buttonStyle(.borderless)
    }
}

let view = Toggles()
PlaygroundPage.current.setLiveView(view)

Published on 18 September 2024