I am using macOS Ventura and Xcode 15.0.1. I have reached out to the original developer, but he does not get the same errors as I get. The code is supposed to create a button. I have tried googling of course, but to no avail. I don't know much about new Swift macros, so I am a bit lost as to what the problem might be. I should also say I am fairly new to SwiftUI, but I am learning every day.
When I run the code, I get the following error:
error: MyPlayground.playground:191:1: error: external macro implementation type 'PreviewsMacros.SwiftUIView' could not be found for macro 'Preview(_:body:)' #Preview {
import Foundation
import SwiftUI
// MARK: - Custom Button Style
struct MobileMeButtonStyle: ButtonStyle {
// MARK: Metrics
@ScaledMetric private var cornerRadius = 12
@ScaledMetric private var horizontalLabelPadding = 12
@ScaledMetric private var verticalLabelPadding = 8
@ScaledMetric private var shadowRadius = 2
@ScaledMetric private var shadowVerticalOffset = 1
// MARK: Immutable Properties
private let strokeLineWidth = 1.0
func makeBody(configuration: Configuration) -> some View {
configuration.label
.labelStyle(.mobileMe)
.padding(.horizontal, horizontalLabelPadding)
.padding(.vertical, verticalLabelPadding)
.background(
RoundedRectangle(cornerRadius: cornerRadius, style: .continuous)
.foregroundStyle(
LinearGradient(
colors: [
Color(red: 58/255, green: 63/255, blue: 66/255),
Color(red: 58/255, green: 63/255, blue: 66/255),
Color(red: 73/255, green: 76/255, blue: 80/255)
],
startPoint: .top,
endPoint: .bottom
)
)
.overlay(
// Top reflection
ReflectionContainer {
UnevenRoundedRectangle(
cornerRadii: .init(
topLeading: cornerRadius,
bottomLeading: (cornerRadius * 0.43).rounded(.down),
bottomTrailing: (cornerRadius * 0.43).rounded(.down),
topTrailing: cornerRadius
),
style: .continuous
)
.foregroundStyle(
LinearGradient(
colors: [
Color.white,
Color.white.opacity(0.24)
],
startPoint: .top,
endPoint: .bottom
)
)
.blendMode(.plusLighter)
.opacity(0.24)
}
)
.overlay(
// Inner light stroke
RoundedRectangle(cornerRadius: cornerRadius, style: .continuous)
.strokeBorder(
LinearGradient(
colors: [
Color.white,
Color.white.opacity(0.2),
Color.white.opacity(0.24)
],
startPoint: .top,
endPoint: .bottom
),
lineWidth: strokeLineWidth
)
.blendMode(.plusLighter)
.opacity(0.3)
)
.overlay(
// Outer shadow stroke
RoundedRectangle(cornerRadius: cornerRadius, style: .continuous)
.inset(by: -strokeLineWidth)
.strokeBorder(
LinearGradient(
colors: [
Color.black.opacity(0.8),
Color.black
],
startPoint: .top,
endPoint: .bottom
),
lineWidth: strokeLineWidth
)
.opacity(0.34)
)
)
.shadow(
color: .black.opacity(0.2),
radius: shadowRadius,
x: 0,
y: shadowVerticalOffset
)
.padding(.leading, 2)
.environment(\.buttonRole, configuration.role)
}
}
// MARK: - Custom Layout
private struct ReflectionContainer: Layout {
func sizeThatFits(
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()
) -> CGSize {
let safeProposal = proposal.replacingUnspecifiedDimensions()
return CGSize(width: safeProposal.width, height: safeProposal.height)
}
func placeSubviews(
in bounds: CGRect,
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()
) {
subviews.first!.place(
at: CGPoint(x: bounds.minX, y: bounds.minY),
proposal: .init(
width: proposal.width ?? 0,
height: (proposal.height ?? 0) / 1.85
)
)
}
}
// MARK: - Custom Label Style
private struct MobileMeLabelStyle: LabelStyle {
// MARK: Environment
@Environment(\.buttonRole) private var role
// MARK: Metrics
@ScaledMetric private var shadowRadius = 2
@ScaledMetric private var shadowVerticalOffset = 1
func makeBody(configuration: Configuration) -> some View {
HStack {
configuration.icon
configuration.title
}
.font(.callout.weight(.medium))
.foregroundStyle(
role == .destructive
? AnyShapeStyle(Color.red.gradient)
: AnyShapeStyle(Color.white.gradient.opacity(0.9))
)
.shadow(
color: .black.opacity(role == .destructive ? 0.3 : 0.6),
radius: shadowRadius,
x: 0,
y: shadowVerticalOffset
)
}
}
// MARK: - Quality Of Life
extension ButtonStyle where Self == MobileMeButtonStyle {
static var mobileMe: Self { MobileMeButtonStyle() }
}
extension LabelStyle where Self == MobileMeLabelStyle {
static var mobileMe: Self { MobileMeLabelStyle() }
}
// MARK: - Environment Extensions
private enum ButtonRoleEnvironmentKey: EnvironmentKey {
static let defaultValue: ButtonRole? = nil
}
extension EnvironmentValues {
var buttonRole: ButtonRole? {
get { self[ButtonRoleEnvironmentKey.self] }
set { self[ButtonRoleEnvironmentKey.self] = newValue }
}
}
// MARK: - Preview
#Preview {
HStack {
Button(action: {}) {
Label(
title: { Text("Today") },
icon: { EmptyView() }
)
}
Button(role: .destructive, action: {}) {
Label(
title: { EmptyView() },
icon: { Image(systemName: "trash.fill") }
)
}
}
.padding(.horizontal, 16)
.padding(.vertical, 16)
.background(
RoundedRectangle(cornerRadius: 30, style: .continuous)
.foregroundStyle(
LinearGradient(
colors: [
Color(red: 72/255, green: 77/255, blue: 81/255),
Color(red: 46/255, green: 48/255, blue: 54/255)
],
startPoint: .top,
endPoint: .bottom
)
)
)
.buttonStyle(.mobileMe)
}
You seem to be using an Xcode Playground. Xcode Playgrounds don't support SwiftUI previews. (See also)
Xcode Playgrounds have live views, which also allow you to "preview" a SwiftUI view. This is slightly different to SwiftUI Previews, e.g. you cannot choose different devices - the view is sort of just displayed "in a vacuum".
Rather than using Xcode Playgrounds, you can create a new Xcode project, and paste the code there. Open the "Canvas" if it doesn't appear automatically:
Alternatively, if you do want to preview this in an Xcode playground,
import PlaygroundSupport
and changeto
Manually open the live view if it is not open already. It'd look something like this:
Note that there is a similarly-named app called Swift Playgrounds, which does support SwiftUI Previews.