5

I'm working on an app + widget with Xcode 15 Beta. The widget works as expected on iOS 17 Beta simulators, but when running on my device with iOS 17 beta, it displays "Please adopt containerBackground API" instead of the desired content.

enter image description here

I searched around, and could only find containerBackground on LocationButton, but I'm not using Core Location at all. Can anybody point out why it is referred here?

CodeBrew
  • 6,457
  • 2
  • 43
  • 48
  • I believe it may be referring to https://developer.apple.com/documentation/SwiftUI/View/containerBackground(_:for:) – ScottM Jul 01 '23 at 15:16
  • @ScottM Yes indeed. Could yo add your reply as an answer and I will accept it? – CodeBrew Jul 02 '23 at 21:54

2 Answers2

7

Great Filip Němeček article here on adapting a hot fix for this so it still works on iOS16 devices.

TLDR:

Add an extension with the OS check:

extension View {
    func widgetBackground(_ backgroundView: some View) -> some View {
        if #available(iOSApplicationExtension 17.0, *) {
            return containerBackground(for: .widget) {
                backgroundView
            }
        } else {
            return background(backgroundView)
        }
    }
}

Add widgetBackground to all of your different widgets (pick your background view/color, of course):

var body: some View {
    VStack {
        // widget content
    }
    .widgetBackground(Color.black)
}

Also, he mentions an interesting note about iOS17 widgets, where they force additional margin padding on your design.

You can disable this while generating WidgetConfiguration:

var body: some WidgetConfiguration {
    //IntentConfiguration stuff
    .contentMarginsDisabled()
}
William T.
  • 12,831
  • 4
  • 56
  • 53
6

The modifier in question is .containerBackground(_:for:), which is new in iOS 17 and related platform versions.

With it you can specify the background for your entire widget as a modifier to your custom view, e.g.:

VStack {
  Text("My widget")
    .foregroundStyle(.secondary)
}
.containerBackground(.red.gradient, for: .widget)

Note that in some places, e.g., if your widget displays in the new StandBy mode, the container background may not display at all.

You can customise this behaviour by adding the modifier containerBackgroundRemovable(false) – although that may prevent your widget from being shown at all in some contexts.

A preferable option is to subscribe to the environment variable \.showsWidgetContainerBackground to tweak your widget if you're in a context where the background is not showing.

More details can be found in the WWDC video Bringing widgets to new places.

ScottM
  • 7,108
  • 1
  • 25
  • 42