As has been discussed previously during iOS 14, the syntax of the WidgetBundleBuilder is such that it isn't possible to have any control logic. You can only list the widgets that you want to include. No if statements or other conditionals allowed.
This is going to be a problem for supporting the new systemExtraLarge widget for my app in iPadOS 15. For configuration reasons, I have one widget for each size in my app currently: SmallWidget, MediumWidget, and LargeWidget. I can create an ExtraLargeWidget for iPadOS 15, but that causes a problem in iOS 14 because that widget can't be included and the WidgetBundle list is static.
It seems that if you have multiple supportedFamilies (e.g. [.systemLarge, .systemExtraLarge]) in the widget, then the system works as expected and the extra large option just doesn't appear on iOS 14 or iPhone on iOS 15 but the rest do. However, for my case I can only specify one family per widget and when it doesn't exist on iOS 14, I have to set supportedFamilies = []. If I include this widget in my WidgetBundle then it seems to break the system and none of the widgets show up in the widget gallery on iOS 14 as if they aren't installed.
So I need one of two things:
-
A way to specify a dynamic list of widgets in my WidgetBundle using conditionals (e.g. if #available(iOS 15, *)) in order to not include my ExtraLarge widget on iOS 14.
-
A way to include a widget with supportedFamilies = [] so that it just skips that widget from the bundle rather than not displaying the widgets in the gallery at all.
As far as I can tell, neither of these is possible and therefore I cannot add the extra large widget in my app for iPadOS 15 without something drastic like dropping support for iOS 14, which isn't going to happen.
Has anyone else hit this issue in iPadOS 15 yet? Is there a workaround for this issue I haven't thought of yet?
I've tried various possible solutions and none worked out.
The WidgetBundleBuilder ResultBuilder lacks some implementation details which prevent the usage of if #available
and single if statements, viz:
- buildOptional
- buildLimitedAvailability
I tried writing an extension for WidgetBundleBuilder with the above two methods but I'm not sure what the implementation would look like. The following makes things work but it may be unreliable.
extension WidgetBundleBuilder {
public static func buildOptional<C0>(_ component: C0?) -> some Widget where C0:Widget {
return component ?? SomeWidget() as! C0
}
public static func buildLimitedAvailability<C0>(_ component: C0) -> some Widget where C0:Widget {
return component
}
}