Xcode 15: Disable the content margins for widget preview? (contentMarginsDisabled)

Hi guys,

I am migrating my widgets to iOS 17 and because I already manage my layout margins, I just want to disable to new built-in widget content margins.

I did it by using ".contentMarginsDisabled()" on the WidgetConfiguration and it works fine at run time.

WIDGET CODE

struct MyWidget: Widget {
    
    let kind: String = "MyWidget"

    var body: some WidgetConfiguration {

        return IntentConfiguration(kind: kind, intent: MyWidgetIntent.self, provider: WidgetProvider<MyWidgetIntent>()) { entry in
            WidgetView<MyWidgetIntent>(entry: entry)
        }
        .configurationDisplayName("My Widget")
        .supportedFamilies([WidgetFamily.systemMedium])
        .contentMarginsDisabled() // <-- HERE
    }
}

RESULT

Nevertheless, when previewing the WidgetView in a WidgetPreviewContext I didn't find anyway to disable the content margins (because manipulating directly the view and not a WidgetConfiguration).

PREVIEW CODE

struct MyWidget_Previews: PreviewProvider {
    
    static var previews: some View {
        WidgetView<MyWidgetIntent>(entry: WidgetEntry<MyWidgetIntent>())
            // .padding(-16) Need to add this negative padding to disable margin


            .previewContext(
                WidgetPreviewContext(family: .systemMedium))
    }
}

Do you know how to disable the content margins for widget preview?

Answered by Developer Tools Engineer in 760956022

Hi,

Sorry to hear you are having problems getting widget previews working as expected. The issue you are hitting here is that the old PreviewProvider + .widgetPreviewContext API to preview a view in the context of a Widget but at no point does the API get connected to the actual Widget instance nor the Configuration of it. This means that a lot of the new Widget capabilities added this year aren't available when rendering the preview (such as any of the modifiers like .contentMarginsDisabled() that you might call on your Configuration).

Instead if you switch to using the new Preview macro API that was added this year for your widget preview needs you should see things rendered like you'd expect.

So something like:

#Preview("Provider", as: .systemMedium, using: MyWidgetIntent.mock) {
    MyWidget()
} timelineProvider: {
    WidgetProvider<MyWidgetIntent>()
}

or

#Preview("Timeline", as: .systemMedium) {
    MyWidget()
} timeline: {
    WidgetEntry<MyWidgetIntent>(),
    WidgetEntry<MyWidgetIntent>(),
    WidgetEntry<MyWidgetIntent>()
}
Accepted Answer

Hi,

Sorry to hear you are having problems getting widget previews working as expected. The issue you are hitting here is that the old PreviewProvider + .widgetPreviewContext API to preview a view in the context of a Widget but at no point does the API get connected to the actual Widget instance nor the Configuration of it. This means that a lot of the new Widget capabilities added this year aren't available when rendering the preview (such as any of the modifiers like .contentMarginsDisabled() that you might call on your Configuration).

Instead if you switch to using the new Preview macro API that was added this year for your widget preview needs you should see things rendered like you'd expect.

So something like:

#Preview("Provider", as: .systemMedium, using: MyWidgetIntent.mock) {
    MyWidget()
} timelineProvider: {
    WidgetProvider<MyWidgetIntent>()
}

or

#Preview("Timeline", as: .systemMedium) {
    MyWidget()
} timeline: {
    WidgetEntry<MyWidgetIntent>(),
    WidgetEntry<MyWidgetIntent>(),
    WidgetEntry<MyWidgetIntent>()
}

I had this issue too, and found that contentMarginsDisabled() also doesn't work in the preview (even with the newer syntax) if:

  • Your widgets are exposed in a WidgetBundle and the one you're previewing isn't in the bundle
  • Your widget definition's kind property isn't unique
Xcode 15: Disable the content margins for widget preview? (contentMarginsDisabled)
 
 
Q