Como posso controlar o gesto de toque no widget?

Sep 26 2020

Estou escrevendo um widget com o WidgetKit e quero tornar o conteúdo do widget clicável. Por exemplo, se os usuários clicarem para ver a classificação, quero abrir a guia de classificação quando o aplicativo se tornar ativo.

Tentei usar a notificação entre o aplicativo e o widget, mas o gesto de tocar não está funcionando, adicionei imprimir dentro do gesto de tocar, mas ele não apareceu no console. Além disso, adicionei o mesmo grupo de aplicativos a ambos.

WidgetView:

struct LargeWidget : View {
    
    @State var standings : [StandingsTable]
    
    var body: some View {
        VStack(alignment:.leading){
            if standings.count > 0{
                HStack(spacing:5){
                    Text("#").foregroundColor(.gray)
                        .frame(width: 30)
                    Text("Team".localized).foregroundColor(.gray)
                    Spacer()
                    Text("_D".localized).foregroundColor(.gray)
                        .frame(width: 30)
                    Text("_L".localized).foregroundColor(.gray)
                        .frame(width: 30)
                    Text("_W".localized).foregroundColor(.gray)
                        .frame(width: 30)
                    Text("_P".localized).foregroundColor(.gray)
                        .frame(width: 30)
                }
                Divider()
                ForEach(0..<5, id: \.self) { i in
                    HStack(spacing:5){
                        Text(standings[i].rank)
                            .font(.system(size: 15))
                            .padding(.vertical, 3)
                            .frame(width: 30)
                            .background(Color(UIColor.systemBackground))
                            .cornerRadius(4)
                        Text(standings[i].name)
                            .lineLimit(1)
                            .padding(.leading, 5)
                        Spacer()
                        Text(standings[i].drawn)
                            .frame(width: 30)
                        Text(standings[i].lost)
                            .frame(width: 30)
                        Text(standings[i].won)
                            .frame(width: 30)
                        Text(standings[i].points)
                            .frame(width: 30)
                    }
                    .padding(.vertical, 5)
                    .background(standings[i].name == "Besiktas" ? Color(UIColor.systemGray6) : Color.clear)
                    .cornerRadius(8)
                    
                }
                Spacer(minLength: 0)
            }else{
                Text("Large")
                    .padding()
            }
        }.padding()
        .onTapGesture {
            print("clicked to standings")
            DispatchQueue.main.async(execute: {
                NotificationCenter.default.post(name: NSNotification.Name("standings"), object: nil, userInfo: nil)
            })
        }
    }
}

e aqui ContentView no aplicativo:

import SwiftUI

extension NSNotification {
    static let openStandings = NSNotification.Name.init("standings")
}

struct ContentView: View {
    
    @State var show: Bool = false
    
    var body: some View {
        NavigationView{
            Text("Hello, world!")
                .padding()
        }.sheet(isPresented: self.$show) {
            VStack{
                Text("Notification")
                    .padding()
            }
        }
        .onReceive(NotificationCenter.default.publisher(for: NSNotification.openStandings))
        { obj in
            self.show.toggle()
        }
    }
}

Captura de tela do widget

Respostas

HalilİbrahimYÜCE Sep 26 2020 at 22:17

Ok, eu criei um novo projeto com ambientes SwiftUI (não os antigos AppDelegate e SceneDelegate).

Então eu uso o Link para ações de toque e eu o obtive com o modificador .onOpenURL no ContentView. Funciona :)

ContentView:

import SwiftUI

enum SelectedTab: Hashable {
    case home
    case standings
    case options
}

struct ContentView: View {
    
    @State var selectedTab: SelectedTab = .home
    
    var body: some View {
        TabView(selection: self.$selectedTab) {
            Text("Home")
                .tabItem {
                    Image(systemName: "house")
                        .renderingMode(.template)
                    Text("Home")
                }.tag(SelectedTab.home)
            Text("Standings")
                .tabItem {
                    Image(systemName: "list.number")
                        .renderingMode(.template)
                    Text("Standings")
                }.tag(SelectedTab.standings)
            Text("Options")
                .tabItem {
                    Image(systemName: "gear")
                        .renderingMode(.template)
                    Text("Options")
                }.tag(SelectedTab.options)
                .onOpenURL { (url) in
                    if url.absoluteString == "widget-deeplink://standings"{
                        self.selectedTab = .standings
                    }
                }
        }
    }
}

Exemplo de uso de link no widget:

Link(destination: URL(string: "widget-deeplink://standings")!) {
    Text("Link Test")
}