5

I would like to preview my WidgetKit widget in my main app.

The widget lays out differently for .systemSmall and .systemMedium sizes.

When I set .environment(\.widgetFamily, .systemSmall) in the main app I get a build error:

Key path value type 'WritableKeyPath<EnvironmentValues, WidgetFamily>' cannot be converted to contextual type 'KeyPath<EnvironmentValues, WidgetFamily>'

If I don't set a value, it defaults to .systemMedium.

Is there a way to use .systemSmall?

lewis
  • 2,936
  • 2
  • 37
  • 72

1 Answers1

11

The widgetFamily environment key is not setup in the app for obvious reasons, but you can implement it yourself.

First you need to make WidgetFamily conform to EnvironmentKey like this:

extension WidgetFamily: EnvironmentKey {
    public static var defaultValue: WidgetFamily = .systemMedium
}

Then you need to add your custom environment key, like this:

extension EnvironmentValues {
  var widgetFamily: WidgetFamily {
    get { self[WidgetFamily.self] }
    set { self[WidgetFamily.self] = newValue }
  }
}

Now you can use the .environment() modifier in the app:

struct ContentView: View {
    var body: some View {
        InterestingWidgetEntryView(entry: .init(date: .init()))
            .environment(\.widgetFamily, .systemSmall)
    }
}

This is how I created my widget view:

struct InterestingWidgetEntryView : View {
    @Environment(\.widgetFamily) var family
    var entry: Provider.Entry
    
    var body: some View {
        switch family {
        case .systemSmall:
            Text("Small")
        case .systemMedium:
            Text("Medium")
        case .systemLarge:
            Text("Large")
        default:
            Text("Some other WidgetFamily in the future.")
        }
    }
}

And this is the result:

Widget view loaded in app using correct family

Keep in mind that the widget view will not have the widget size, you'll have to calculate that yourself.

EmilioPelaez
  • 18,758
  • 6
  • 46
  • 50