Enfin, avec la version bêta 5, nous pouvons passer par programmation à une vue parent. Cependant, il y a plusieurs endroits dans mon application où une vue a un bouton "Enregistrer" qui conclut un processus en plusieurs étapes et revient au début. Dans UIKit, j'utilise popToRootViewController (), mais je n'ai pas réussi à trouver un moyen de faire de même dans SwiftUI.
Voici un exemple simple du modèle que j'essaie de réaliser. Des idées?
import SwiftUI
struct DetailViewB: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View {
VStack {
Text("This is Detail View B.")
Button(action: { self.presentationMode.value.dismiss() } )
{ Text("Pop to Detail View A.") }
Button(action: { /* How to do equivalent to popToRootViewController() here?? */ } )
{ Text("Pop two levels to Master View.") }
}
}
}
struct DetailViewA: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View {
VStack {
Text("This is Detail View A.")
NavigationLink(destination: DetailViewB() )
{ Text("Push to Detail View B.") }
Button(action: { self.presentationMode.value.dismiss() } )
{ Text("Pop one level to Master.") }
}
}
}
struct MasterView: View {
var body: some View {
VStack {
Text("This is Master View.")
NavigationLink(destination: DetailViewA() )
{ Text("Push to Detail View A.") }
}
}
}
struct ContentView: View {
var body: some View {
NavigationView {
MasterView()
}
}
}
Définir le modificateur de vue isDetailLink
sur false
sur un NavigationLink
est la clé pour faire fonctionner pop-to-root. isDetailLink
est true
par défaut et s'adapte à la vue contenant. Sur l'iPad paysage par exemple, une vue fractionnée est séparée et isDetailLink
garantit que la vue de destination sera affichée sur le côté droit. Régler isDetailLink
sur false
signifie par conséquent que la vue de destination sera toujours insérée dans la pile de navigation; ainsi peut toujours être sauté.
En plus de définir isDetailLink
sur false
sur NavigationLink
, passez la liaison isActive
à chaque vue de destination suivante. Enfin, lorsque vous souhaitez passer à la vue racine, définissez la valeur sur false
et tout disparaîtra automatiquement:
import SwiftUI
struct ContentView: View {
@State var isActive : Bool = false
var body: some View {
NavigationView {
NavigationLink(
destination: ContentView2(rootIsActive: self.$isActive),
isActive: self.$isActive
) {
Text("Hello, World!")
}
.isDetailLink(false)
.navigationBarTitle("Root")
}
}
}
struct ContentView2: View {
@Binding var rootIsActive : Bool
var body: some View {
NavigationLink(destination: ContentView3(shouldPopToRootView: self.$rootIsActive)) {
Text("Hello, World #2!")
}
.isDetailLink(false)
.navigationBarTitle("Two")
}
}
struct ContentView3: View {
@Binding var shouldPopToRootView : Bool
var body: some View {
VStack {
Text("Hello, World #3!")
Button (action: { self.shouldPopToRootView = false } ){
Text("Pop to root")
}
}.navigationBarTitle("Three")
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
J'ai passé les dernières heures à essayer de résoudre le même problème. Pour autant que je puisse voir, pas de moyen facile de le faire avec la version bêta 5. La seule façon que j'ai trouvée, c'est très hacky mais ça marche. Ajoutez essentiellement un éditeur à votre DetailViewA qui sera déclenché à partir de DetailViewB. Dans DetailViewB, fermez la vue et informez l'éditeur, qui fermera lui-même DetailViewA.
struct DetailViewB: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var publisher = PassthroughSubject<Void, Never>()
var body: some View {
VStack {
Text("This is Detail View B.")
Button(action: { self.presentationMode.value.dismiss() } )
{ Text("Pop to Detail View A.") }
Button(action: {
DispatchQueue.main.async {
self.presentationMode.wrappedValue.dismiss()
self.publisher.send()
}
} )
{ Text("Pop two levels to Master View.") }
}
}
}
struct DetailViewA: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var publisher = PassthroughSubject<Void, Never>()
var body: some View {
VStack {
Text("This is Detail View A.")
NavigationLink(destination: DetailViewB(publisher:self.publisher) )
{ Text("Push to Detail View B.") }
Button(action: { self.presentationMode.value.dismiss() } )
{ Text("Pop one level to Master.") }
}
.onReceive(publisher, perform: { _ in
DispatchQueue.main.async {
print("Go Back to Master")
self.presentationMode.wrappedValue.dismiss()
}
})
}
}
[MISE À JOUR] J'y travaille toujours, car sur la dernière version bêta 6, je n'ai toujours pas de solution.
J'ai trouvé un autre moyen de revenir à la racine, mais cette fois je perds l'animation et je vais directement à la racine. L'idée est de forcer un rafraîchissement de la vue racine, conduisant ainsi à un nettoyage de la pile de navigation.
Mais au final, seul Apple pourrait apporter une solution appropriée, car la gestion de la pile de navigation n'est pas disponible dans SwiftUI.
NB: La solution simple par notification ci-dessous fonctionne sur iOS et non sur watchOS, car watchOS efface la vue racine de la mémoire après 2 niveaux de navigation. Mais avoir une classe externe gérant l'état de watchOS devrait simplement fonctionner.
struct DetailViewB: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
@State var fullDissmiss:Bool = false
var body: some View {
SGNavigationChildsView(fullDissmiss: self.fullDissmiss){
VStack {
Text("This is Detail View B.")
Button(action: { self.presentationMode.wrappedValue.dismiss() } )
{ Text("Pop to Detail View A.") }
Button(action: {
self.fullDissmiss = true
} )
{ Text("Pop two levels to Master View with SGGoToRoot.") }
}
}
}
}
struct DetailViewA: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
@State var fullDissmiss:Bool = false
var body: some View {
SGNavigationChildsView(fullDissmiss: self.fullDissmiss){
VStack {
Text("This is Detail View A.")
NavigationLink(destination: DetailViewB() )
{ Text("Push to Detail View B.") }
Button(action: { self.presentationMode.wrappedValue.dismiss() } )
{ Text("Pop one level to Master.") }
Button(action: { self.fullDissmiss = true } )
{ Text("Pop one level to Master with SGGoToRoot.") }
}
}
}
}
struct MasterView: View {
var body: some View {
VStack {
Text("This is Master View.")
NavigationLink(destination: DetailViewA() )
{ Text("Push to Detail View A.") }
}
}
}
struct ContentView: View {
var body: some View {
SGRootNavigationView{
MasterView()
}
}
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
#endif
struct SGRootNavigationView<Content>: View where Content: View {
let cancellable = NotificationCenter.default.publisher(for: Notification.Name("SGGoToRoot"), object: nil)
let content: () -> Content
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
@State var goToRoot:Bool = false
var body: some View {
return
Group{
if goToRoot == false{
NavigationView {
content()
}
}else{
NavigationView {
content()
}
}
}.onReceive(cancellable, perform: {_ in
DispatchQueue.main.async {
self.goToRoot.toggle()
}
})
}
}
struct SGNavigationChildsView<Content>: View where Content: View {
let notification = Notification(name: Notification.Name("SGGoToRoot"))
var fullDissmiss:Bool{
get{ return false }
set{ if newValue {self.goToRoot()} }
}
let content: () -> Content
init(fullDissmiss:Bool, @ViewBuilder content: @escaping () -> Content) {
self.content = content
self.fullDissmiss = fullDissmiss
}
var body: some View {
return Group{
content()
}
}
func goToRoot(){
NotificationCenter.default.post(self.notification)
}
}
Voici ma solution pop arrière lente, animée et un peu rude utilisant onAppear, valable pour XCode 11 et iOS 13.1:
import SwiftUI
import Combine
struct NestedViewLevel3: View {
@Binding var resetView:Bool
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View {
VStack {
Spacer()
Text("Level 3")
Spacer()
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}) {
Text("Back")
.padding(.horizontal, 15)
.padding(.vertical, 2)
.foregroundColor(Color.white)
.clipped(antialiased: true)
.background(
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.blue)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 40, alignment: .center)
)}
Spacer()
Button(action: {
self.$resetView.wrappedValue = true
self.presentationMode.wrappedValue.dismiss()
}) {
Text("Reset")
.padding(.horizontal, 15)
.padding(.vertical, 2)
.foregroundColor(Color.white)
.clipped(antialiased: true)
.background(
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.blue)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 40, alignment: .center)
)}
Spacer()
}
.navigationBarBackButtonHidden(false)
.navigationBarTitle("Level 3", displayMode: .inline)
.onAppear(perform: {print("onAppear level 3")})
.onDisappear(perform: {print("onDisappear level 3")})
}
}
struct NestedViewLevel2: View {
@Binding var resetView:Bool
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View {
VStack {
Spacer()
NavigationLink(destination: NestedViewLevel3(resetView:$resetView)) {
Text("To level 3")
.padding(.horizontal, 15)
.padding(.vertical, 2)
.foregroundColor(Color.white)
.clipped(antialiased: true)
.background(
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.gray)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 40, alignment: .center)
)
.shadow(radius: 10)
}
Spacer()
Text("Level 2")
Spacer()
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}) {
Text("Back")
.padding(.horizontal, 15)
.padding(.vertical, 2)
.foregroundColor(Color.white)
.clipped(antialiased: true)
.background(
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.blue)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 40, alignment: .center)
)}
Spacer()
}
.navigationBarBackButtonHidden(false)
.navigationBarTitle("Level 2", displayMode: .inline)
.onAppear(perform: {
print("onAppear level 2")
if self.$resetView.wrappedValue {
self.presentationMode.wrappedValue.dismiss()
}
})
.onDisappear(perform: {print("onDisappear level 2")})
}
}
struct NestedViewLevel1: View {
@Binding var resetView:Bool
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View {
VStack {
Spacer()
NavigationLink(destination: NestedViewLevel2(resetView:$resetView)) {
Text("To level 2")
.padding(.horizontal, 15)
.padding(.vertical, 2)
.foregroundColor(Color.white)
.clipped(antialiased: true)
.background(
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.gray)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 40, alignment: .center)
)
.shadow(radius: 10)
}
Spacer()
Text("Level 1")
Spacer()
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}) {
Text("Back")
.padding(.horizontal, 15)
.padding(.vertical, 2)
.foregroundColor(Color.white)
.clipped(antialiased: true)
.background(
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.blue)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 40, alignment: .center)
)}
Spacer()
}
.navigationBarBackButtonHidden(false)
.navigationBarTitle("Level 1", displayMode: .inline)
.onAppear(perform: {
print("onAppear level 1")
if self.$resetView.wrappedValue {
self.presentationMode.wrappedValue.dismiss()
}
})
.onDisappear(perform: {print("onDisappear level 1")})
}
}
struct RootViewLevel0: View {
@Binding var resetView:Bool
var body: some View {
NavigationView {
VStack {
Spacer()
NavigationLink(destination: NestedViewLevel1(resetView:$resetView)) {
Text("To level 1")
.padding(.horizontal, 15)
.padding(.vertical, 2)
.foregroundColor(Color.white)
.clipped(antialiased: true)
.background(
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.gray)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 40, alignment: .center)
)
.shadow(radius: 10)
}
//.disabled(false)
//.hidden()
Spacer()
}
}
//.frame(width:UIScreen.main.bounds.width,height: UIScreen.main.bounds.height - 110)
.navigationBarTitle("Root level 0", displayMode: .inline)
.navigationBarBackButtonHidden(false)
.navigationViewStyle(StackNavigationViewStyle())
.onAppear(perform: {
print("onAppear root level 0")
self.resetNavView()
})
.onDisappear(perform: {print("onDisappear root level 0")})
}
func resetNavView(){
print("resetting objects")
self.$resetView.wrappedValue = false
}
}
struct ContentView: View {
@State var resetView = false
var body: some View {
RootViewLevel0(resetView:$resetView)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Cela a pris du temps, mais j'ai compris comment utiliser la navigation complexe dans swiftui. L'astuce consiste à collecter tous les états de vos vues, qui indiquent s'ils sont affichés.
Commencez par définir un NavigationController. J'ai ajouté la sélection pour l'onglet tabview et les valeurs booléennes indiquant si une vue spécifique est affichée
import SwiftUI
final class NavigationController: ObservableObject {
@Published var selection: Int = 1
@Published var tab1Detail1IsShown = false
@Published var tab1Detail2IsShown = false
@Published var tab2Detail1IsShown = false
@Published var tab2Detail2IsShown = false
}
configurer la tabulation avec deux onglets et lier notre NavigationController.selection à la tabulation:
import SwiftUI
struct ContentView: View {
@EnvironmentObject var nav: NavigationController
var body: some View {
TabView(selection: self.$nav.selection){
FirstMasterView()
.tabItem {
Text("First")
}
.tag(0)
SecondMasterView()
.tabItem {
Text("Second")
}
.tag(1)
}
}
}
À titre d'exemple, il s'agit d'une navigationStacks
import SwiftUI
struct FirstMasterView: View {
@EnvironmentObject var nav: NavigationController
var body: some View {
NavigationView{
VStack{
NavigationLink(destination: FirstDetailView(), isActive: self.$nav.tab1Detail1IsShown) {
Text("go to first detail")
}
} .navigationBarTitle(Text("First MasterView"))
}
}
}
struct FirstDetailView: View {
@EnvironmentObject var nav: NavigationController
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View {
VStack(spacing: 20) {
Text("first detail View").font(.title)
NavigationLink(destination: FirstTabLastView(), isActive: self.$nav.tab1Detail2IsShown) {
Text("go to last detail on nav stack")
}
Button(action: {
self.nav.tab2Detail1IsShown = false //true will go directly to detail
self.nav.tab2Detail2IsShown = false
self.nav.selection = 1
}) { Text("Go to second tab")
}
}
//in case of collapsing all the way back
//there is a bug with the environment object
//to go all the way back I have to use the presentationMode
.onReceive(self.nav.$tab1Detail2IsShown, perform: { (out) in
if out == false {
self.presentationMode.wrappedValue.dismiss()
}
})
}
}
struct FirstTabLastView: View {
@EnvironmentObject var nav: NavigationController
var body: some View {
Button(action: {
self.nav.tab1Detail1IsShown = false
self.nav.tab1Detail2IsShown = false
}) {Text("Done and go back to beginning of navigation stack")
}
}
}
J'espère que je pourrais expliquer l'approche, qui est assez orientée vers l'état SwiftUI.
Pour moi, afin d'obtenir un contrôle total sur la navigation qui manque toujours dans swiftUI, je viens d'intégrer la vue SwiftUI dans un UINavigationController
. à l'intérieur de SceneDelegate
. Prenez note que je cache la barre de navigation afin d'utiliser la NavigationView comme affichage.
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
UINavigationBar.appearance().tintColor = .black
let contentView = OnBoardingView()
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
let hostingVC = UIHostingController(rootView: contentView)
let mainNavVC = UINavigationController(rootViewController: hostingVC)
mainNavVC.navigationBar.isHidden = true
window.rootViewController = mainNavVC
self.window = window
window.makeKeyAndVisible()
}
}
}
Et puis j'ai créé ce protocole et cette extension, HasRootNavigationController
import SwiftUI
import UIKit
protocol HasRootNavigationController {
var rootVC:UINavigationController? { get }
func Push<Content:View>(view: Content, animated:Bool)
func setRootNavigation<Content:View>(views:[Content], animated:Bool)
func pop(animated: Bool)
func popToRoot(animated: Bool)
}
extension HasRootNavigationController where Self:View {
var rootVC:UINavigationController? {
guard let scene = UIApplication.shared.connectedScenes.first,
let sceneDelegate = scene as? UIWindowScene,
let rootvc = sceneDelegate.windows.first?.rootViewController
as? UINavigationController else { return nil }
return rootvc
}
func Push<Content:View>(view: Content, animated:Bool = true) {
rootVC?.pushViewController(UIHostingController(rootView: view), animated: animated)
}
func setRootNavigation<Content:View>(views: [Content], animated:Bool = true) {
let controllers = views.compactMap { UIHostingController(rootView: $0) }
rootVC?.setViewControllers(controllers, animated: animated)
}
func pop(animated:Bool = true) {
rootVC?.popViewController(animated: animated)
}
func popToRoot(animated: Bool = true) {
rootVC?.popToRootViewController(animated: animated)
}
}
Après cela, sur ma vue SwiftUI, j'ai utilisé/implémenté le protocole et l'extension HasRootNavigationController
extension YouSwiftUIView:HasRootNavigationController {
func switchToMainScreen() {
self.setRootNavigation(views: [MainView()])
}
func pushToMainScreen() {
self.Push(view: [MainView()])
}
func goBack() {
self.pop()
}
func showTheInitialView() {
self.popToRoot()
}
}
voici l'essentiel de mon code au cas où j'aurais des mises à jour. https://Gist.github.com/michaelhenry/945fc63da49e960953b72bbc567458e6
Merci "Malhal" pour votre solution @Binding. Il me manquait le modificateur .isDetailLink(false)
. Ce que j'ai appris de votre code.
Dans mon cas, je ne veux pas utiliser @Binding à chaque vue suivante.
C'est donc ma solution où j'utilise EnvironmentObject.
Étape 1: créer un AppState
ObservableObject
import SwiftUI
import Combine
class AppState: ObservableObject {
@Published var moveToDashboard: Bool = false
}
Étape 2: créer une instance de AppState
et ajouter contentView
dans SceneDelegate
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Create the SwiftUI view that provides the window contents.
let contentView = ContentView()
let appState = AppState()
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView:
contentView
.environmentObject(appState)
)
self.window = window
window.makeKeyAndVisible()
}
}
Étape 3: Code de ContentView.Swift
Je mets donc à jour la valeur appState
de la dernière vue de la pile qui utilise .onReceive()
Je capture dans le contentView pour mettre à jour isActive
à false pour le NavigationLink.
La clé ici est d'utiliser .isDetailLink(false)
avec NavigationLink. Sinon, cela ne fonctionnera pas.
import SwiftUI
import Combine
class AppState: ObservableObject {
@Published var moveToDashboard: Bool = false
}
struct ContentView: View {
@EnvironmentObject var appState: AppState
@State var isView1Active: Bool = false
var body: some View {
NavigationView {
VStack {
Text("Content View")
.font(.headline)
NavigationLink(destination: View1(), isActive: $isView1Active) {
Text("View 1")
.font(.headline)
}
.isDetailLink(false)
}
.onReceive(self.appState.$moveToDashboard) { moveToDashboard in
if moveToDashboard {
print("Move to dashboard: \(moveToDashboard)")
self.isView1Active = false
self.appState.moveToDashboard = false
}
}
}
}
}
// MARK:- View 1
struct View1: View {
var body: some View {
VStack {
Text("View 1")
.font(.headline)
NavigationLink(destination: View2()) {
Text("View 2")
.font(.headline)
}
}
}
}
// MARK:- View 2
struct View2: View {
@EnvironmentObject var appState: AppState
var body: some View {
VStack {
Text("View 2")
.font(.headline)
Button(action: {
self.appState.moveToDashboard = true
}) {
Text("Move to Dashboard")
.font(.headline)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Je n'ai pas exactement le même problème mais j'ai du code qui change la vue racine d'une qui ne prend pas en charge une pile de navigation à une qui le fait. L'astuce est que je ne le fais pas dans SwiftUI - je le fais dans le SceneDelegate
et remplace le UIHostingController
par un nouveau.
Voici un extrait simplifié de mon SceneDelegate
:
func changeRootToOnBoarding() {
guard let window = window else {
return
}
let onBoarding = OnBoarding(coordinator: notificationCoordinator)
.environmentObject(self)
window.rootViewController = UIHostingController(rootView: onBoarding)
}
func changeRootToTimerList() {
guard let window = window else {
return
}
let listView = TimerList()
.environmentObject(self)
window.rootViewController = UIHostingController(rootView: listView)
}
Puisque le SceneDelegate
se met dans l'environnement, n'importe quelle vue enfant peut ajouter
/// Our "parent" SceneDelegate that can change the root view.
@EnvironmentObject private var sceneDelegate: SceneDelegate
puis appelez des fonctions publiques sur le délégué. Je pense que si vous avez fait quelque chose de similaire qui a conservé le View
mais a créé un nouveau UIHostingController
pour cela et remplacé window.rootViewController
cela pourrait fonctionner pour vous.
J'ai récemment créé un projet open source appelé swiftui-navigation-stack
( https://github.com/biobeats/swiftui-navigation-stack ). Il s'agit d'une pile de navigation alternative pour SwiftUI. Jetez un oeil à la README pour tous les détails, c'est vraiment facile à utiliser.
Tout d'abord, si vous souhaitez naviguer entre les écrans (c'est-à-dire les vues plein écran), définissez votre propre vue Screen
simple:
struct Screen<Content>: View where Content: View {
let myAppBackgroundColour = Color.white
let content: () -> Content
var body: some View {
ZStack {
myAppBackgroundColour.edgesIgnoringSafeArea(.all)
content()
}
}
}
Ensuite, intégrez votre racine dans un NavigationStackView
(comme vous le feriez avec le standard NavigationView
):
struct RootView: View {
var body: some View {
NavigationStackView {
Homepage()
}
}
}
Créons maintenant quelques vues enfant juste pour vous montrer le comportement de base:
struct Homepage: View {
var body: some View {
Screen {
PushView(destination: FirstChild()) {
Text("Push FORWARD")
}
}
}
}
struct FirstChild: View {
var body: some View {
Screen {
VStack {
PopView {
Text("JUST POP")
}
PushView(destination: SecondChild()) {
Text("Push FORWARD")
}
}
}
}
}
struct SecondChild: View {
var body: some View {
Screen {
VStack {
PopView {
Text("JUST POP")
}
PopView(destination: .root) {
Text("POP TO ROOT")
}
}
}
}
}
Vous pouvez exploiter PushView
et PopView
pour naviguer dans les deux sens. Bien sûr, votre vue de contenu à l'intérieur du SceneDelegate
doit être:
// Create the SwiftUI view that provides the window contents.
let contentView = RootView()
Le résultat est: