I have multiple Widget
s for my iOS/iPadOS/watchOS app. I have one widget with supported family .systemLarge
.
struct MyWidget: Widget {
var body: some WidgetConfiguration {
StaticConfiguration(...)
.xxx // some modifiers
.supportedFamilies([.systemLarge])
}
}
I want this widget to be supported on new stand-by location so I need to support family .systemSmall
as well (I want to reuse body
). But since I don’t want this .systemSmall
widget in home screen’s gallery I need to use .disfavoredLocations([.homeScreen], for: [.systemSmall])
as well.
Unfortunetely, I’m supporting iOS 15 and 16 as well so I need to wrap this modifier somehow into #available(iOS 17.0, *)
. But… this can’t be done since there is no type-erased WidgetConfiguration
.
Then I was thinking about something like this with the help of WidgetBundle
:
@available(iOS 17.0, *)
struct MyWidgetIOS17: Widget {
var body: some WidgetConfiguration {
var widget = MyWidget()
return widget.body.disfavoredLocations([.homeScreen], for: [.systemSmall])
}
}
@main
struct Widgets: WidgetBundle {
var body: some Widget {
if #available(iOS 17.0, *) {
MyWidgetIOS17()
} else {
MyWidget()
}
}
}
But… while
if #available(iOS 17.0, *) {
MyWidgetIOS17()
}
works,
if #available(iOS 17.0, *) {
MyWidgetIOS17()
} else {
MyWidget()
}
does not.
Does anybody know how to use disfavoredLocations
below iOS 17 while still reusing the Widget
s body?
2
Answers
My solution is to add
MyWidget
for all versions with supported family.systemLarge
as it used to support and then addMyWidgetIOS17
which supports just.systemSmall
and is wrapped in#available(iOS 17.0, *)
if statement. This way I can reuseMyWidget
's body and still be able to usedisfavoredLocations
.Also note, that these two widgets have to have different
kind
.I solved this issue with an extension on
WidgetConfiguration
:The only downside is that you cannot pass
WidgetLocation
as a parameter because the symbol is only available on iOS 17+.