— iOS, Widgets, iOS 17, SwiftUI, StandBy Mode — 1 min read
The arrival of iOS 17 last year brought exciting new features, but also a few hurdles for developers working with widgets. Let's tackle two common issues: missing backgrounds and unwanted padding.
When you update your widget for iOS 17, you might find its background has mysteriously disappeared. This is because Standby mode removes elements deemed non-essential. To combat this, Apple introduced the containerBackground
modifier. Here's how to use it, along with a handy backport extension for pre-iOS 17 versions:
1struct MyWidget: Widget {2
3 var body: some WidgetConfiguration {4 StaticConfiguration(kind: "MyWidget") {5 // ... your widget content here6
7 .widgetBackground(backgroundView: Color.white) // Set your desired background color8 }9 }10}11
12// Backport Extension (Optional): For compatibility with older iOS versions13extension View {14 func widgetBackground(backgroundView: some View) -> some View {15 if #available(iOSApplicationExtension 17.0, *) {16 return containerBackground(for: .widget) {17 backgroundView18 }19 } else {20 return background(backgroundView)21 }22 }23}
The containerBackground
modifier takes two arguments: a context and a closure that defines the background for that context. Here, we're setting the background for the standard widget context using a Color
view. You can define backgrounds for other contexts as needed.
This code snippet also includes a backport extension named widgetBackground
. This extension checks the iOS version and applies either containerBackground
for iOS 17 or background
for older versions, ensuring your widget displays a background consistently.
Another quirk of StandBy mode is the addition of extra padding around your widget. This can throw off your widget's layout. To address this, Apple offers the contentMarginsDisabled
modifier. Here's how to use it, again with a backport extension:
1struct MyWidget: Widget {2
3 var body: some WidgetConfiguration {4 StaticConfiguration(kind: "MyWidget") {5 // ... your widget content here6
7 .contentMarginsDisabledIfAvailable() // Disable system-added margins8 }9 }10}11
12// Backport Extension (Optional): For compatibility with older iOS versions13extension WidgetConfiguration {14 func contentMarginsDisabledIfAvailable() -> some WidgetConfiguration {15 if #available(iOSApplicationExtension 17.0, *) {16 return self.contentMarginsDisabled()17 } else {18 return self19 }20 }21}
The contentMarginsDisabled
modifier simply tells the system not to add its own padding.
Important Note: The backport extension for contentMarginsDisabled is not strictly necessary if your widget only supports iOS 15 and above. While the modifier exists in iOS 15 and 16, it doesn't have any effect on those versions.