Trouble with new XCode 15 Preview Macro for Widgets

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

Accepted Reply

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:

  1. 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
  2. Reproduce the issue
  3. 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)
  4. In the sheet that appears, click "Generate Report" in the bottom left of the sheet
  5. Attach (or make from the folder) the resulting zip file to the bug (will be named something like previews-diagnostics-0123456789.zip)
  6. Generate the sysdiagnose(s) and attach those too

Replies

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:

  1. 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
  2. Reproduce the issue
  3. 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)
  4. In the sheet that appears, click "Generate Report" in the bottom left of the sheet
  5. Attach (or make from the folder) the resulting zip file to the bug (will be named something like previews-diagnostics-0123456789.zip)
  6. Generate the sysdiagnose(s) and attach those too

It may be that your project is continuing to support older platform versions. At least, mine is, and adding an @available attribute to the macro resolved it:

@available(iOS 17.0, *)
#Preview("Small", as: .systemSmall) {
  ... etc ...
Post not yet marked as solved Up vote reply of jp- Down vote reply of jp-
  • works!

  • This solution works.

    I previously used it like this @available(iOSApplicationExtension 17.0, *) and it worked till beta 5 or 6, I don't remember now. But then broke.

  • Thank you very much, your assessment was on point and this fixed the issue! As I'm unfamiliar with this forum platform I accidentally marked the other answer as accepted, otherwise I would've kept this one! hahaha

Add a Comment