I'm trying to get rid of the auto-padding added recently by iOS 17, and I found out that you can use the WidgetConfigurations properly with the new Preview Macro, but I'm having trouble getting it to work, and some help would be much appreciated.
Here's my code:
struct ChartEntry: TimelineEntry {
let date: Date
let configuration: ConfigurationIntent
...
static func getSampleEntry() -> ChartEntry {
let sample = ChartEntry(date: Date(), configuration: WidgetUtils.getSampleConfiguration())
return sample
}
}
struct PreviewTimelineProvider: TimelineProvider {
typealias Entry = ChartEntry
func placeholder(in context: Context) -> ChartEntry {
ChartEntry.getSampleEntry()
}
func getSnapshot(in context: Context, completion: @escaping (ChartEntry) -> Void) {
completion(ChartEntry.getSampleEntry())
}
func getTimeline(in context: Context, completion: @escaping (Timeline<ChartEntry>) -> Void) {
var entries: [ChartEntry] = []
let currentDate = Date()
for hourOffset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
let entry = ChartEntry(date: entryDate, configuration: WidgetUtils.getSampleConfiguration())
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
struct DailyHoursOfSunshine: Identifiable {
let id = UUID()
var date: Date
var hoursOfSunshine: Double
init(date: Date, hoursOfSunshine: Double) {
self.date = date
self.hoursOfSunshine = hoursOfSunshine
}
}
var data = [
DailyHoursOfSunshine(date: Date(), hoursOfSunshine: 0), // Sunday
DailyHoursOfSunshine(date: Date().addingTimeInterval(86400), hoursOfSunshine: 60), // Monday
DailyHoursOfSunshine(date: Date().addingTimeInterval(2 * 86400), hoursOfSunshine: 50), // Tuesday
DailyHoursOfSunshine(date: Date().addingTimeInterval(3 * 86400), hoursOfSunshine: 72), // Wednesday
DailyHoursOfSunshine(date: Date().addingTimeInterval(4 * 86400), hoursOfSunshine: 88), // Thursday
DailyHoursOfSunshine(date: Date().addingTimeInterval(5 * 86400), hoursOfSunshine: 70), // Friday
DailyHoursOfSunshine(date: Date().addingTimeInterval(6 * 86400), hoursOfSunshine: 120) // Saturday
]
struct ChartSmallView: View {
var entry: ChartEntry
var body: some View {
VStack {
Spacer()
VStack(alignment: .leading, spacing: 0) {
Chart(data) {
AreaMark(
x: .value("Week", $0.date),
y: .value("Hours of Sunshine", $0.hoursOfSunshine)
)
.alignsMarkStylesWithPlotArea()
}
.foregroundStyle(
.linearGradient (
colors: [.blue, .clear],
startPoint: .top,
endPoint: .bottom
)
)
.chartXAxis(.hidden)
.chartYAxis(.hidden)
.chartLegend(.hidden)
.padding([.horizontal], 3)
}
Spacer()
}
.frame(maxWidth: .infinity)
}
}
#Preview("Small", as: .systemSmall) {
ChartWidget()
} timelineProvider: {
PreviewTimelineProvider()
}
NOTE: There's nothing much on my ChartWidget struct, just the configuration to disable the margins and declare the preferred size and calling the ChartSmallView struct, I just didn't copy it here because it is in another file and I'm a little busy to go out excluding sensible information. I would actually prefer to call just ChartSmallView on my preview, but then I wouldn't have access to the configuration that disables the awful contextualized margins.
The code compiles just fine, but when the preview tries to build it, the following error happens:
== PREVIEW UPDATE ERROR:
CompileDylibError: Failed to build ChartSmallView.swift
Compiling failed: cannot convert value of type 'PreviewTimelineProvider' to closure result type 'any View'
@__swiftmacro_63MyWidgetExtension_PreviewReplacement_ChartSmallView_133_77BD2C8074131F1FDF53BC08606762A7Ll0F0fMf_.swift
------------------------------
@available(iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0, xrOS 1.0, *)
struct $s63MyWidgetExtension_PreviewReplacement_ChartSmallView_133_77BD2C8074131F1FDF53BC08606762A7Ll0F0fMf_15PreviewRegistryfMu_: DeveloperToolsSupport.PreviewRegistry {
static let fileID: String = "MyWidgetExtension_PreviewReplacement_ChartSmallView_1/ChartSmallView.1.preview-thunk.swift"
static let line: Int = 125
static let column: Int = 1
static func makePreview() throws -> DeveloperToolsSupport.Preview {
DeveloperToolsSupport.Preview("Small", as: .systemSmall) {
ChartWidget()
} timelineProvider: {
PreviewTimelineProvider()
}
}
}
------------------------------
/.../MyWidgetExtension.build/Objects-normal/x86_64/ChartSmallView.1.preview-thunk.swift:137:13: error: cannot convert value of type 'PreviewTimelineProvider' to closure result type 'any View'
PreviewTimelineProvider()
^~~~~~~~~~~~~~~~~~~~~~~~~
as! any View
I have also attempted to use the Preview Macro in the following way:
#Preview("Small", as: .systemSmall) {
ChartWidget()
} timeline: {
ChartEntry.getSampleEntry()
}
But achieved the same result.
If anyone has any idea of what I'm doing wrong, I would appreciate the help. I couldn't find much material online to help me here
Hi,
Sorry to hear you are having problems getting widget previews working. This error can happen if the file in question is missing an import WidgetKit
. If that is already present, or adding it doesn't fix the issue, then the best next step will be to file a feedback with diagnostics so we can take a look.
Steps to generate helpful diagnostics:
- Download and install the logging profile on all devices involved. Instructions and profiles are available here: https://developer.apple.com/bug-reporting/profiles-and-logs/?name=swift
- Reproduce the issue
- Click the "Diagnostics" button in the error banner in Previews' Canvas area (or if the banner is missing you can use the menu: Editor > Canvas > Diagnostics)
- In the sheet that appears, click "Generate Report" in the bottom left of the sheet
- Attach (or make from the folder) the resulting zip file to the bug (will be named something like
previews-diagnostics-0123456789.zip
) - Generate the sysdiagnose(s) and attach those too