swiftswiftuiwidgetkit

Widget working on preview but not on simulator


I have the following iOS widget that works perfectly on the preview panel but does not load (shows the placeholder state) on the simulator.

I have other widgets written almost identically all working perfectly so I'm not sure what's wrong with this one.


import WidgetKit
import AppIntents
import SwiftUI

private let defaultSkiresortDetail = SkiresortDetail(
    id: "foobar"
)

private struct SkiresortWidgetIntent: WidgetConfigurationIntent {
    static var title: LocalizedStringResource = "Ski Resort"
    static var description = IntentDescription("Select the ski resort to display.")
    
    @Parameter(title: "Ski Resort")
    var skiresort: SkiresortDetail
}


private struct SkiresortQuery: EntityQuery {
    func entities(for identifiers: [SkiresortDetail.ID]) -> [SkiresortDetail] {
        return [defaultSkiresortDetail]
    }
    
    func suggestedEntities() -> [SkiresortDetail] {
        [defaultSkiresortDetail]
    }
    
    func defaultResult() -> SkiresortDetail? {
        suggestedEntities().first
    }
}

private struct SkiresortDetail: AppEntity {
    let id: String
    
    static var typeDisplayRepresentation: TypeDisplayRepresentation = "Ski Resort"
    static var defaultQuery = SkiresortQuery()
    
    var displayRepresentation: DisplayRepresentation {
        DisplayRepresentation(title: "\(id)")
    }
}

private struct SkiresortWidgetProvider: AppIntentTimelineProvider {
    func placeholder(in context: Context) -> SkiresortWidgetTimelineEntry {
        return SkiresortWidgetTimelineEntry(date: .now)
    }
    
    func snapshot(for configuration: SkiresortWidgetIntent, in context: Context) -> SkiresortWidgetTimelineEntry {
        return SkiresortWidgetTimelineEntry(date: .now)
    }
    
    func timeline(for configuration: SkiresortWidgetIntent, in context: Context) -> Timeline<SkiresortWidgetTimelineEntry> {
        return Timeline(
            entries: [
                SkiresortWidgetTimelineEntry(date: .now)
            ],
            policy: .atEnd
        )
    }
    
}

private struct SkiresortWidgetTimelineEntry: TimelineEntry {
    let date: Date
}

private struct SkiresortWidgetView: View {
    let entry: SkiresortWidgetTimelineEntry
    
    var body: some View {
        Text("Hello")
        .font(.title3)
        .containerBackground(for: .widget) {}
    }
}

struct SkiresortWidget: Widget {
    let kind: String = "Skiresort_Status"
    
    var body: some WidgetConfiguration {
        AppIntentConfiguration(
            kind: kind,
            intent: SkiresortWidgetIntent.self,
            provider: SkiresortWidgetProvider()
        ) {
            entry in SkiresortWidgetView(entry: entry)
        }
        .configurationDisplayName("Ski Resort Status")
        .description("Your favorite ski resort status at a glance.")
        .supportedFamilies([.systemMedium])
    }
}

#Preview(as: .systemMedium) {
    SkiresortWidget()
} timeline: {
    SkiresortWidgetTimelineEntry(date: .now)
}

The widget does not show the "Edit widget" option on long press either.

What am I doing wrong?


Solution

  • I found the problem!

    The WidgetConfigurationIntent must be public, I did mark it as private.

    Xcode will not complain about it or warn you in any way though.