StaticConfiguration.init(kind:provider:placeholder:content:) deprecated warning

In Xcode 12 Beta 3, I am getting a warning that StaticConfiguration.init(kind:provider:placeholder:content:) is deprecated and that StaticConfiguration.init(kind:provider:content:) should be used instead.

My question is how does one specify a placeholder view now?

Thanks,
Rob
Answered by Documentation Engineer in 623062022
You should implement placeholder(with: Context) to return a TimelineEntry that contains whatever you need for your placeholder. Note that unlike snapshot and timeline which are asynchronous with a completion block, the placeholder method is synchronous and you return a timeline entry immediately. So you want to be fast to return that entry.

When your widget's view is rendered for placeholder purposes it's given the placeholder entry and you can render your view accordingly. Note, there's some new SwiftUI support for marking a view as redacted. What should happen is that when WidgetKit renders the widget's view using the placeholder timeline entry, it would automatically render the view using .redacted(reason: .placeholder). Unfortunately that isn't working in Beta 3, but should be fixed in an upcoming seed.

Let us know if that doesn't make sense. If you have trouble getting it working please file Feedback Assistant report with details, and post the number here.


TimelineProvider now has placeholder(with: Context).
You should implement placeholder(with: Context) to return a TimelineEntry that contains whatever you need for your placeholder. Note that unlike snapshot and timeline which are asynchronous with a completion block, the placeholder method is synchronous and you return a timeline entry immediately. So you want to be fast to return that entry.

When your widget's view is rendered for placeholder purposes it's given the placeholder entry and you can render your view accordingly. Note, there's some new SwiftUI support for marking a view as redacted. What should happen is that when WidgetKit renders the widget's view using the placeholder timeline entry, it would automatically render the view using .redacted(reason: .placeholder). Unfortunately that isn't working in Beta 3, but should be fixed in an upcoming seed.

Let us know if that doesn't make sense. If you have trouble getting it working please file Feedback Assistant report with details, and post the number here.


Is there a reason why the new placeholder function does not have access to the Intent data? It would be useful to be able to access some settings from the IntentConfiguration to e.g. use colors the user selected also for the placeholder view. Or did I miss something?

Markus
ok, I implemented the new (in beta 3) method: placeholder(with: Context). The widget shows up on the device when I run locally, but when distributed using TestFlight, HomeWidget disappears and cannot be added.

Here his my code for the TimeLineProvider. What am I missing?

Code Block struct Provider: TimelineProvider {
    public typealias Entry = SimpleEntry
    let dict_dummy = ["Gizmo": ["SOC": 89, "ratedRange": 196, "estimatedRange": 185, "unit": "mi", "isTestUser": true]]
    public func snapshot(with context: Context, completion: @escaping (SimpleEntry) -> ()) {
        var  dict = defaults?.dictionary(forKey: Constants.WIDGET_DICT)
        if dict == nil {
            dict = dict_dummy
        }
        let entry = SimpleEntry(date: Date(), dict: dict)
        completion(entry)
    }
    public func timeline(with context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        let currentDate = Date()
        let refreshDate = Calendar.current.date(byAdding: .minute, value: 10, to: currentDate)!
        let dict = defaults?.dictionary(forKey: Constants.WIDGET_DICT)
        let entry = SimpleEntry(date: Date(), dict: dict)
        let timeline = Timeline(entries: [entry], policy: .after(refreshDate))
        completion(timeline)
    }
    func placeholder(with: Context) -> SimpleEntry {
        let entry = SimpleEntry(date: Date(), dict: dict_dummy)
        return entry
    }
}
@main
struct HomeWidget: Widget {
    private let kind: String = "HomeWidget"
    public var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind, provider: Provider()) { entry in
            HomeWidgetEntryView(entry: entry)
        }
        .configurationDisplayName("Stats Widget")
        .description("Shows battery SoC and Rated Range")
        .supportedFamilies([.systemSmall, .systemMedium])
    }
}


Is there any documentation available to indicate the difference between snapshot and placeholder. While I do see that @pdm noted that snapshot is asynchronous, I was under the impression that snapshot's goal is to provide a quick representation of the widget, as will be previewed in the widget gallery. I was also under the impression that placeholder is relevant in cases where the widget will be rendered on the home screen before data is available. In effect;

Snapshot - Should provide real data, asynchronously, but should return this data as quickly as possible for rendering in the widget gallery.

Placeholder - Should provide data as quickly as possible, synchronously, which will be (in a future beta) automatically rendered as redacted where relevant to provide a rendered UI.

Timeline - The standard timeline entries can be provided asynchronously, and as they do not need to be provided quickly (necessarily), can gather the relevant data from network resources or the app for optimal experience.

Do I have that right?
@brandonK212 where you able to get a sample of the differences between
Code Block
Snapshot
and
Code Block
Placeholder
  • I am having the same issue.

StaticConfiguration.init(kind:provider:placeholder:content:) deprecated warning
 
 
Q