Search code examples
swiftswiftuiios14widgetkit

Update Widget when appearance changes


I would need to know if any of you know a system in SwiftUI to update a Widget when the appearance changes from light mode to dark mode and vice versa.

I can change text and images but I use a method to display a screenshot of a map and I should run it every time the appearance changes to get the correct map color.


Solution

    1. Create two screenshots (one per theme) and pass it in the entry:
    struct SimpleEntry: TimelineEntry {
        let date: Date
        let mapScreenshots: [ColorScheme: Image]
    }
    
    struct Provider: TimelineProvider {
        ...
    
        func getTimeline(in context: Context, completion: @escaping (Timeline<SimpleEntry>) -> Void) {
            let entry = SimpleEntry(
                date: Date(),
                mapScreenshots: [
                    // replace with actual map screenshots
                    .dark: Image(systemName: "plus"),
                    .light: Image(systemName: "minus"),
                ]
            )
            let timeline = Timeline(entries: [entry], policy: .never)
            completion(timeline)
        }
    }
    
    1. Use @Environment(\.colorScheme) to react to theme changes:
    struct WidgetEntryView: View {
        @Environment(\.colorScheme) var colorScheme
    
        var entry: Provider.Entry
    
        var body: some View {
            if let screenshot = entry.mapScreenshots[colorScheme] {
                screenshot
            }
        }
    }