Complication Widget using AccessoryWidgetGroup

I want to get which button in AccessoryWidgetGroup was pressed in the Watch App, but I can't.

When I use Button(_:intent:), it works in Smart Stack, but it doesn't work in Complication Widget.
Using widgetURL(_:) always gets the URL of the first button.

Below is a snippet of the code I tried. All codes can be found here.

struct MyWatchWidgetEntryView : View {
    var entry: Provider.Entry

    var body: some View {
        AccessoryWidgetGroup("Widget Group") {
            MyWatchWidgetEntryButton(intent: .init(id: "001", imageName: "star.fill"))
            MyWatchWidgetEntryButton(intent: .init(id: "002", imageName: "heart.fill"))
            MyWatchWidgetEntryButton(intent: .init(id: "003", imageName: "leaf.fill"))
        }
    }
}

//Button View
private struct MyWatchWidgetEntryButton: View {
    @Environment(\.showsWidgetContainerBackground) var showsWidgetContainerBackground
    let intent: MyAppIntent

    var body: some View {
        Button(intent: intent) {
            ZStack {
                if showsWidgetContainerBackground {
                    Color.black
                } else {
                    AccessoryWidgetBackground()
                }
                VStack {
                    Image(systemName: intent.imageName)
                        .font(.headline)
                    Text(intent.id)
                        .font(.system(size: 10, weight: .bold))
                }
            }
        }
        .buttonStyle(.plain)
        .widgetURL(URL(string: "widget://" + intent.id))
    }
}

Does anyone know how to do this?

Thank you.

Answered by DTS Engineer in 806916022

I got a chance to try your code and found something interesting: When I tap a widget group element in the complication, the app intent is not really triggered. It seems that watchOS detects that the tap is on the whole widget group, and launches your watchOS app with the first widget URL.

Interestingly, if I remove the .buttonStyle(.plain) view modifier, as shown below, watchOS will detect that the tap is on the widget group element, and triggers the associated app intent, which triggers the .performAppIntent notification and passes your app the right data.

Button(intent: intent) { 
    ...
    }
    //.buttonStyle(.plain)
    .widgetURL(URL(string: "widget://" + intent.id))

So removing .buttonStyle(.plain) may be the easiest way to fix your issue. If the plain style button doesn't fit your design, you can probably manage to make the widget group element bigger, which I believe should work as well.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

I haven't had a chance to take a closer look yet, but am wondering if this is something related to AppIntent. For debugging purpose, if you use Button, rather than Button(intent:...), will the widget URL be passed to your watchOS app correctly?

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Thanks for your reply!

I tried using Button instead of Button(intent:...) and the widget URL wasn't passed correctly. It always returns the URL of the first button.

Accepted Answer

I got a chance to try your code and found something interesting: When I tap a widget group element in the complication, the app intent is not really triggered. It seems that watchOS detects that the tap is on the whole widget group, and launches your watchOS app with the first widget URL.

Interestingly, if I remove the .buttonStyle(.plain) view modifier, as shown below, watchOS will detect that the tap is on the widget group element, and triggers the associated app intent, which triggers the .performAppIntent notification and passes your app the right data.

Button(intent: intent) { 
    ...
    }
    //.buttonStyle(.plain)
    .widgetURL(URL(string: "widget://" + intent.id))

So removing .buttonStyle(.plain) may be the easiest way to fix your issue. If the plain style button doesn't fit your design, you can probably manage to make the widget group element bigger, which I believe should work as well.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Thanks for your reply!

I was able to confirm that the method you suggested worked correctly.

I also discovered that it works correctly without AccessoryWidgetBackground().

Button(intent: intent) {
    ZStack {
        if showsWidgetContainerBackground {
            Color.black
        } else {
            Color.primary.opacity(0.15)
            //AccessoryWidgetBackground()
        }
        ...
    }
}
.buttonStyle(.plain)
.widgetURL(URL(string: "widget://" + intent.id))

This problem seems to occur when using both AccessoryWidgetBackground() and .buttonStyle(.plain).

Maybe this is a bug? I'll add this information to the feedback(FB15151000).

Thank you very much for your help!

Complication Widget using AccessoryWidgetGroup
 
 
Q