web-dev-qa-db-fra.com

Navigation + Tabview + Feuille brisée dans iOS 15

Il ressemble à la navigation + tache Tabview + est cassé dans iOS 15.

Quand je fais ceci: contentView -> DétacherView -> Feuille inférieure

Lorsque la feuille inférieure se présente, la vue Detail est automatiquement surveillé de la pile: https://www.youtube.com/watch?v=gGUTAX0l4

Je m'attends à ce que la vue Detail reste là même lorsque la feuille inférieure apparaît. Quelqu'un a-t-il une idée de la raison pour laquelle cela se produit et comment le réparer?

Voici mon exemple de code:

import Combine
import SwiftUI
import RealmSwift

struct ContentView: View {

    var body: some View {
        NavigationView {
            TabView {
                TabItemView(num: 1)
                    .tabItem {
                        Text("One")
                    }
                TabItemView(num: 2)
                    .tabItem {
                        Text("Two")
                    }
            }
        }
    }
}

struct TabItemView: View {

    private let num: Int

    init(num: Int) {
        self.num = num
    }

    var body: some View {
        NavigationLink(destination: DetailView(text: "Detail View \(num)")) {
            Text("Go to Detail View")
        }
    }
}

struct DetailView: View {

    @State private var showingSheet = false

    private let text: String

    init(text: String) {
        self.text = text
    }

    var body: some View {
        Button("Open Sheet") {
            showingSheet.toggle()
        }.sheet(isPresented: $showingSheet) {
            Text("Sheet Text")
        }
    }
}

Cela fonctionne sur iOS 14 BTW

Mise à jour 1:

Essayé @ Sebastian's Suggestion de mettre NavigationView à l'intérieur de TabView. Bien que cela corrige le bogue NAV, il a fondamentalement changé le comportement (je ne veux pas montrer les onglets dans DetailView).

A également essayé sa suggestion d'utiliser Introspect pour définir navigationController.hidesBottomBarWhenPushed = true sur la destination NavigationLink, mais cela n'a rien fait:

struct ContentView: View {
    
    var body: some View {
        TabView {
            NavigationView {
                TabItemView(num: 1)
            }.tabItem {
                Text("One")
            }
            NavigationView {
                TabItemView(num: 2)
            }.tabItem {
                Text("Two")
            }
        }
    }
}

struct TabItemView: View {
    
    private let num: Int
    
    init(num: Int) {
        self.num = num
    }
    
    var body: some View {
        NavigationLink(destination: DetailView(text: "Detail View \(num)").introspectNavigationController { navigationController in
            navigationController.hidesBottomBarWhenPushed = true
        }) {
            Text("Go to Detail View")
        }
    }
}

struct DetailView: View {
    
    @State private var showingSheet = false
    
    private let text: String
    
    init(text: String) {
        self.text = text
    }
    
    var body: some View {
        Button("Open Sheet") {
            showingSheet.toggle()
        }.sheet(isPresented: $showingSheet) {
            Text("Sheet Text")
        }
    }
}
4
skywalkerdude

Vous devez renvoyer comment vous nichez TabView & NavigationView. Au lieu d'imbriquer plusieurs TabView vues à l'intérieur d'un NavigationView, utilisez le composant TabView comme composant parent, avec un NavigationView pour chaque onglet.

C'est ainsi que l'actualisée ContentView ressemblerait à:

struct ContentView: View {
    var body: some View {
        TabView {
            NavigationView {
                TabItemView(num: 1)
            }
            .tabItem {
                Text("One")
            }
            
            NavigationView {
                TabItemView(num: 2)
            }
            .tabItem {
                Text("Two")
            }
        }
    }
}

Cela a du sens et est plus correct: les onglets doivent toujours être visibles, mais vous souhaitez afficher une pile de navigation différente avec un contenu différent dans chaque onglet.

Qu'il fonctionnait précédemment ne le rendait pas plus correct - Swiftui a probablement changé d'avis sur la gestion des situations inattendues. Cela, et le manque de messages d'erreur dans ces situations, constitue l'inconvénient d'utiliser un cadre qui essaie de rendre quelque chose que vous jetez!


Si l'objectif est spécifiquement de masquer les onglets lorsque vous appuyez sur une nouvelle vue sur une navigationView (E.G., lors de la prise en charge d'une conversation dans une application de messagerie), vous devez utiliser une solution différente. Apple a ajouté le UIViewController.hidesBottomBarWhenPushed Propriété à Uikit pour supporter ce cas d'utilisation spécifique.

Cette propriété est définie sur l'UIViewController qui, lorsqu'elle est présentée, ne doit pas afficher une barre d'outils. En d'autres termes: pas l'uoinavigationController ou l'UITABBARCONTROLLER, mais l'enfant UIViewController que vous appuyez sur l'UINAVIGATIONController.

Cette propriété n'est pas prise en charge à Swiftui Nativement. Vous pouvez la définir à l'aide de SWIFTUI-Introspect ou écrivez simplement la structure de navigation de votre application à l'aide de Uikit et écrivez les vues à l'intérieur à SWIFTUI, en lestenant à l'aide UIHostingViewController =.

1
Sebastian