TabView avec «PageTabViewStyle» ne met pas à jour son contenu lorsque @State var change

Aug 20 2020

Je suis tombé sur un problème étrange dans SwiftUI. J'ai créé une vue simple qui ne contient qu'un bouton et un TabView qui utilise le PageViewStyle. Il semble que TabView ne met pas à jour correctement son contenu en fonction de l'état de la variable. Il semble que le contenu soit mis à jour d'une manière ou d'une autre, mais la vue ne sera pas mise à jour comme je m'y attendais

Voici le code de ma vue:

struct ContentView: View {
    @State var numberOfPages: Int = 0
    @State var selectedIndex = 0
    
    var body: some View {
        VStack {
            Text("Tap Me").onTapGesture(count: 1, perform: {
                self.numberOfPages = [2,5,10,15].randomElement()!
                self.selectedIndex = 0
            })
            
            TabView(selection: $selectedIndex){
                ForEach(0..<numberOfPages, id: \.self) { index in
                    Text("\(index)").background(Color.red)
                }
            }
            .frame(height: 300)
            .tabViewStyle(PageTabViewStyle(indexDisplayMode: .automatic))
        }.background(Color.blue)
    }
}

Voici à quoi ressemble le résultat après avoir tapé plusieurs fois sur l'étiquette. L'état initial n'est pas de 0 pages. Après avoir appuyé sur, je m'attendrais à ce que le contenu de TabView change afin que toutes les pages puissent faire défiler et être visibles, mais seul l'indicateur de page le met à jour pour une raison quelconque.

Réponses

7 Asperi Aug 20 2020 at 07:16

TabViews'attend à avoir un conteneur de pages, mais vous n'en avez inclus qu'une HStack(avec son propre contenu dynamique), de plus le nombre de pages en chaînage que vous devez réinitialiser la vue de l'onglet, voici donc un correctif.

Testé avec Xcode 12 / iOS 14

struct ContentView: View {
    @State var numberOfPages: Int = 0

    var body: some View {
        VStack {
            Text("Tap Me").onTapGesture(count: 1, perform: {
                self.numberOfPages = [2,5,10,15].randomElement()!
            })
            if self.numberOfPages != 0 {
                TabView {
                    ForEach(0..<numberOfPages, id: \.self) { index in
                        Text("\(index)").frame(width: 300).background(Color.red)
                    }
                }
                .tabViewStyle(PageTabViewStyle(indexDisplayMode: .automatic))
                .frame(height: 300)
                .id(numberOfPages)
            }
        }
    }
}