Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2021 EssentialsSwiftUI & UI FrameworksApp Services

WWDC21 · 27 min · Essentials / SwiftUI & UI Frameworks / App Services

Principles of great widgets

Explore the foundations of great widgets by keeping them relevant and customizable. Learn how to keep widgets up to date with timeline entries and TimelineReloadPolicies. Discover how to adapt your widget to different presentation environments and physical location. And lastly, find out how to create customizable widgets that someone can personalize to their liking.

Watch at developer.apple.com ↗

Transcript all transcripts

Code shown on screen · 5 snippets

Xcode Previews for Widget Views with Color Scheme Overrides swift · at 15:46 ↗
struct MyWidgetEntryView : View {
    var date: Date

    var body: some View {
        ZStack {
            Rectangle().fill(BackgroundStyle())
            VStack {
                Text("Hello")
            }
        }
    }
}

struct MyWidget_Previews: PreviewProvider {
    static var previews: some View {
        MyWidgetEntryView(date: Date())
            .previewContext(WidgetPreviewContext(family: .systemSmall))
            .environment(\.colorScheme, .dark)
    }
}
Widget Partial Privacy Redactions - Banking Example swift · at 16:34 ↗
struct MyWidgetEntryView : View {

    var body: some View {
        ZStack {
            Rectangle().fill(BackgroundStyle())
            VStack(alignment: .leading) {
                Text("Balance")
                    .font(.largeTitle)
                    .fontWeight(.bold)
                    .foregroundColor(Color.blue)
                Text("$128.45")
                    .privacySensitive()
                    .font(.title2)
                    .foregroundColor(Color.gray)
            }
        }
    }
}
WidgetBundle Example swift · at 23:08 ↗
struct IndividualSymbolWidget : Widget {
    var body: some WidgetConfiguration {
    
}
}

struct StocksOverviewWidget : Widget {
    var body: some WidgetConfiguration {
    
    }
}

@main
struct MyWidgetBundle: WidgetBundle {
    var body: some Widget {
        // Order of these widgets defines the order in the Widget Gallery
        IndividualSymbolWidget()
        StocksOverviewWidget()
    }
}
Static Widget Configuration Example swift · at 25:43 ↗
@main
public struct SampleWidget: Widget {
    public var body: some WidgetConfiguration {
        StaticConfiguration(kind: "com.sample.myStaticSampleWidgetKind",
                            provider: Provider()) { entry in
                                SampleWidgetEntryView(entry: entry)
                            }
        .configurationDisplayName("My Widget")
        .description("This is an example widget.")
    }
}

public struct Provider: TimelineProvider {
    public func timeline(with context: Context,
                         completion: @escaping (Timeline<Entry>) -> ()) {
        let entry = SimpleEntry(date: Date())
        // TODO: Generate a timeline entry
        completion(timeline)
    }
}
Intent Widget Configuration Example swift · at 25:55 ↗
@main
public struct SampleWidget: Widget {
    public var body: some WidgetConfiguration {
        IntentConfiguration(kind: "com.sample.myIntentSampleWidgetKind",
                            intent: SampleConfigurationIntent.self
                            provider: Provider()) { entry in
                                SampleWidgetEntryView(entry: entry)
                            }
        .configurationDisplayName("My Widget")
        .description("This is an example widget.")
    }
}

public struct Provider: IntentTimelineProvider {
    public func timeline(for configuration: SampleConfigurationIntent, with context: Context,
                         completion: @escaping (Timeline<Entry>) -> ()) {
        let entry = SimpleEntry(date: Date(), configuration: configuration)
        // generate a timeline
        completion(timeline)
    }
}

Resources