swiftUI中的NavigationView用法

swiftUI中的NavigationView用法,swiftui,swiftui-navigationlink,Swiftui,Swiftui Navigationlink,我来自Android,正在开发一个非常复杂的应用程序,我希望尽可能多地使用NavigationView。对于我来说,拥有一个视图并使所有元素在该视图上出现和消失似乎是不可能的。 我使用navigationView在导航栏隐藏的视图之间导航。 这种导航或显示视图的方式对用户来说是透明的 经过一些测试,我遇到了一些限制:在第13或14级导航时,所有内容都消失了,应用程序基本上崩溃了 同样,这是两个内容视图之间的直接导航,没有主屏幕 import SwiftUI struct test4: View

我来自Android,正在开发一个非常复杂的应用程序,我希望尽可能多地使用NavigationView。对于我来说,拥有一个视图并使所有元素在该视图上出现和消失似乎是不可能的。 我使用navigationView在导航栏隐藏的视图之间导航。 这种导航或显示视图的方式对用户来说是透明的

经过一些测试,我遇到了一些限制:在第13或14级导航时,所有内容都消失了,应用程序基本上崩溃了

同样,这是两个内容视图之间的直接导航,没有主屏幕

import SwiftUI

struct test4: View {
    
    @State private var intent3: Bool =  false

    var body: some View {
      
        NavigationView{
  
            VStack{
                NavigationLink(destination : test3() , isActive : $intent3) { }
                Text("ver 4")
            .onTapGesture {
            intent3 = true }
                Spacer()
            }
            
        }
        .navigationBarHidden(true)
    }
    
}
这里是直接在两个内容视图之间导航的基本示例。点击14/15次后崩溃。关于任何导航链接,我都会遇到同样的问题。

更新: 通过您添加的代码,我可以看出最初的崩溃是由于每次添加新的
NavigationView
造成的。这就解决了这个问题:


struct ContentView: View {
    var body: some View {
        NavigationView {
            Test3()
        }
    }
}

struct Test4: View {
    @State private var intent3: Bool =  false
    var body: some View {
        VStack{
            NavigationLink(destination : Test3() , isActive : $intent3) { }
            Text("ver 4")
                .onTapGesture {
                    intent3 = true
                }
            Spacer()
        }
        .navigationBarHidden(true)
    }
}

struct Test3: View {
    @State private var intent4: Bool =  false
    var body: some View {
        VStack{
            NavigationLink(destination : Test4() , isActive : $intent4) { }
            Text("ver 3")
                .onTapGesture {
                    intent4 = true }
            Spacer()
        }
        .navigationBarHidden(true)
    }
}

原始答案

但是,有一些解决方案可以弹出到导航层次结构的顶部

一种方法是使用
isActive
管理给定的
NavigationLink
是否显示其视图。可能是这样的:

class NavigationReset : ObservableObject {
    @Published var rootIsActive = false
    
    func popToTop() {
        rootIsActive = false
    }
}

struct ContentView: View {
    @StateObject private var navReset = NavigationReset()
    
    var body: some View {
        NavigationView {
            NavigationLink(destination: DetailView(title: "First"), isActive: $navReset.rootIsActive) {
                Text("Root nav")
            }
        }.environmentObject(navReset)
    }
}

struct DetailView : View {
    var title : String
    @EnvironmentObject private var navReset : NavigationReset
    
    var body: some View {
        VStack {
            NavigationLink(destination: DetailView(title: "\(Date())")) {
                Text("Navigate (\(title))")
            }
            Button("Reset nav") {
                navReset.popToTop()
            }
        }
    }
}
您可以使用的另一个技巧是更改
导航链接上的
id
——一旦发生这种情况,它将重新呈现并变为非活动状态

class NavigationReset : ObservableObject {
    @Published var id = UUID()
    
    func popToTop() {
        id = UUID()
    }
}

struct ContentView: View {
    @StateObject private var navReset = NavigationReset()
    
    var body: some View {
        NavigationView {
            NavigationLink(destination: DetailView(title: "First")) {
                Text("Root nav")
            }
            .id(navReset.id)
        }.environmentObject(navReset)
    }
}

struct DetailView : View {
    var title : String
    @EnvironmentObject private var navReset : NavigationReset
    
    var body: some View {
        VStack {
            NavigationLink(destination: DetailView(title: "\(Date())")) {
                Text("Navigate (\(title))")
            }
            Button("Reset nav") {
                navReset.popToTop()
            }
        }
    }
}

它的工作原理是将第一个
导航链接
(即主屏幕上的链接)标记为
id
。一旦更改了
id
,就会重新创建
NavigationLink
,弹出堆栈中的所有视图。

首先,非常感谢您花费的时间。我很难理解这一切。关于“自身崩溃”:NavigationView{您的评论结尾可能缺少某些内容。如果您需要对我的答案中的某些内容进行更多说明,请告诉我。如果没有额外的代码,其中的许多内容将无法编译。与其将其作为评论添加,不如尝试添加所有相关代码作为问题的编辑。但是,可能只有在我的解决方案由于某些原因,它对您不起作用。很抱歉,这是代码,单击13/14次应该会产生崩溃。我认为这是正常行为,因为它在其他导航视图中正好附加了14次单击。如果导航栏未隐藏,则使其崩溃是有意义的。如果导航不应受到限制(无母视图),为什么需要实现一些额外的代码呢?Thanx再次提醒您,您编辑的示例会崩溃,因为您每次都嵌入了一个新的
NavigationView
。将其仅放在父元素上,效果很好。感谢jpnpdx帮助我解决此问题。对于像我这样的非swift专家,我想补充一点,sol导航中不提供“平等”。与android不同,总是会有一个“根视图”(即使用户看不到它)。根视图的路径将保持不变,即使未关闭。jnpdx带来的其他元素允许一条“直线”到根视图
class NavigationReset : ObservableObject {
    @Published var id = UUID()
    
    func popToTop() {
        id = UUID()
    }
}

struct ContentView: View {
    @StateObject private var navReset = NavigationReset()
    
    var body: some View {
        NavigationView {
            NavigationLink(destination: DetailView(title: "First")) {
                Text("Root nav")
            }
            .id(navReset.id)
        }.environmentObject(navReset)
    }
}

struct DetailView : View {
    var title : String
    @EnvironmentObject private var navReset : NavigationReset
    
    var body: some View {
        VStack {
            NavigationLink(destination: DetailView(title: "\(Date())")) {
                Text("Navigate (\(title))")
            }
            Button("Reset nav") {
                navReset.popToTop()
            }
        }
    }
}