Search code examples
iosswiftwidgetkitipadosxcode13

I can't add systemExtraLarge family in WidgetConfiguration for iOS 15


I want to add an extra large widget as supported family for iOS 15 in my application.

The simplified code for WidgetConfiguration is as follows:

    var body: some WidgetConfiguration {
        IntentConfiguration(
            kind: "Widget",
            intent: SelectProjectIntent.self,
            provider: Provider()
        ) {
            entry in
            ProgressWidgetEntryView(entry: entry)
        }
        .configurationDisplayName("Title")
        .description("Description")
        .supportedFamilies([.systemSmall, .systemMedium, .systemLarge, .systemExtraLarge])
    }

Obviously I can't just simply add extra Large because the following error appears: 'systemExtraLarge' is only available in application extensions for iOS 15.0 or newer

But doing a quick and simple availability checking suggested by XCode I get an error and several warnings. Here is the code:

    var body: some WidgetConfiguration {
        
        if #available(iOSApplicationExtension 15.0, *) {
            
            IntentConfiguration(
                kind: "Widget",
                intent: SelectProjectIntent.self,
                provider: Provider()
            ) {
                entry in
                ProgressWidgetEntryView(entry: entry)
            }
            .configurationDisplayName("Title")
            .description("Description")
            .supportedFamilies([.systemSmall, .systemMedium, .systemLarge, .systemExtraLarge])
            
        } else {
            
            IntentConfiguration(
                kind: "Widget",
                intent: SelectProjectIntent.self,
                provider: Provider()
            ) {
                entry in
                ProgressWidgetEntryView(entry: entry)
            }
            .configurationDisplayName("Title")
            .description("Description")
            .supportedFamilies([.systemSmall, .systemMedium, .systemLarge])
        }
    }

The error is: Function declares an opaque return type, but has no return statements in its body from which to infer an underlying type.

And the two warnings: Result of call to 'supportedFamilies' is unused.

Could someone please explain to me why I am getting this error and how could I fix it so that I can keep the widgets for iOS 14 and add systemExtraLarge for iOS 15?

I'm using XCode Version 13.0 beta 5 on a macOS Monterey Version 12.0 beta (21A5304g)

Thanks in advance.


Solution

  • When you create a View, it's var body is marked as a @ViewBuilder. That allows you to provide multiple child views and use conditionals (learn more). Unfortunately that doesn’t work for the body of a Widget because there is no such thing as a WidgetConfigurationBuilder, so you can only return a single WidgetConfiguration from Widget’s body.

    To solve your problem, take the if-else out of the Widget's body. One way to do that is to move it to a property, like so:

    struct MyWidget: Widget {
        
        private let supportedFamilies:[WidgetFamily] = {
            if #available(iOSApplicationExtension 15.0, *) {
                return [.systemSmall, .systemMedium, .systemLarge, .systemExtraLarge]
            } else {
                return [.systemSmall, .systemMedium, .systemLarge]
            }
        }()
        
        var body: some WidgetConfiguration {
            IntentConfiguration(
                kind: "Widget",
                intent: SelectProjectIntent.self,
                provider: Provider()
            ) {
                entry in
                ProgressWidgetEntryView(entry: entry)
            }
            .configurationDisplayName("Title")
            .description("Description")
            .supportedFamilies(supportedFamilies)
        }
    }