如何在SwiftUI中返回到主视图?

9

我找不到一种方法可以在不显示第二个NavigationView的情况下从ViewB转到ContentView。

struct ContentView: View {
    var body: some View {
        NavigationView{
            VStack {
                Text("Go to ViewA")
                NavigationLink(destination: ViewA()) {Text("Go")}
            }.navigationBarTitle("ContentView")
        }
    }
}

struct ViewA: View {
   @Environment(\.presentationMode) var presentationMode
    var body: some View {
        VStack {
            Text("Go to ViewB")
            NavigationLink(destination: ViewB()) {Text("Go to B")}
            Text("Go back")
            Button(action: { self.presentationMode.wrappedValue.dismiss() }) {Text("Go to ContentView")}
        }.navigationBarTitle("ViewA")
    }
}

struct ViewB: View {
    @Environment(\.presentationMode) var presentationMode
    var body: some View {
        VStack {
            Text("Go Home")
            NavigationLink(destination: ContentView()) {Text("Go")}
            Text("Go back")
            Button(action: { self.presentationMode.wrappedValue.dismiss() }) {Text("Go to ViewB")}
        }.navigationBarTitle("ViewB")
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

在“旧”的Swift中,我可以很容易地创建一个unwindSegue,例如:
@IBAction func unwindToVCMain(segue:UIStoryboardSegue) { }
}

并且可以轻松地像这样调用它

performSegue(withIdentifier: "unwindToVcMain", sender: nil)

enter image description here


1
我也在寻找类似的东西。 - thenakulchawla
2个回答

3
在iOS16及以上版本中
新的编程导航方式非常强大!比旧方式好得多。 新方式使用NavigationStack(path: root)。 路径参数是对NavigationPath的绑定。例如。
@State private var path = NavigationPath()
    var body: some View {
        NavigationStack(path: $path) {
           ...
    }

让我们创建两个结构体来说明这是如何工作的。
struct Fruit: Hashable,Identifiable {
    let id = UUID()
    var name: String
    var number: Int
    static var sample = [Fruit(name: "Apple", number: 2), Fruit(name: "Cherry", number: 3)]
}

struct Vegetable: Hashable,Identifiable {
    let id = UUID()
    var name: String
    var number: Int
    static var sample = [Vegetable(name: "Carrot", number: 2), Vegetable(name: "Zucchini", number: 3)]
}

新的导航风格是数据驱动的。 在这里,我创建了标签和链接... NavigationLink(value:label:) 但是如果我有水果或蔬菜,目的地将会不同。
 .navigationDestination(for: Fruit.self) { fruit in
     VStack {
     ...
     }

所以,如果我有一个蔬菜或水果模型,根据链接中选择的数据类型,导航目标将不同,并且会呈现不同的视图。
那么让我们把这个放在NavigationStack中。让我们从NavigationLink开始:
Form {
    Section("Fruits") {
       ForEach(Fruit.sample) { fruit in
          NavigationLink(value: fruit) {
               HStack {
                 Text("\(fruit.number)")
                 Text(fruit.name)
               }
           }
       }
    }
    Section("Veggies") {
        ForEach(Vegetable.sample) { fruit in
           NavigationLink(value: fruit) {
                 HStack {
                   Text("\(fruit.number)")
                   Text(fruit.name)
                 }
             }
           }
         }
     }

现在,NavigationDestination 的样子将是这样的:

 .navigationDestination(for: Fruit.self) { fruit in
     VStack {
         Text(fruit.name)
         HStack{
             let count = path.count
             Text("level: \(count)")
         }
         Form {
             Section("Veggies") {
                 ForEach(Vegetable.sample) { veg in
                     NavigationLink(value: veg) {
                         HStack {
                             Text("\(veg.number)")
                             Text(veg.name)
                         }
                     }
                 }
             }
         }
         Button("Unwind") {
             path.removeLast(path.count)
         }
     }

再下面再加上同样的,但是针对蔬菜的,比如:
.navigationDestination(for: Vegetable.self) { veg in
         VStack {
                   ...
}

现在你可以从列表导航到另一个列表,应用程序会显示你所处的深度,取决于路径中收集了多少项。然后你可以解开。这将重置路径属性为空,并再次显示起始页面!
屏幕将会是这样的……还有解开按钮。

fridge

并导航...

navigation

希望这能帮到你!
对于iOS 15及以下版本
使用旧的NavigationView和NavigationLink(destination:isactive:label)
首先,将你的第一个视图嵌入导航控制器中。
然后,在下一个视图中插入一个导航链接。NavigationLink有不同的初始化方法。 选择带有isActive参数的这个方法:

ScreenshotNavLink

一开始可能有点让人费解,但是在NavigationLink中的isActive参数,在链接被点击并且导航到下一个屏幕时会变为true

它创建了一个实例,当活动时呈现目标

如果我传递一个绑定来跟踪此属性的状态,如果在我的后续视图链中的任何时间将其再次设置为false,它将重置并返回到原始屏幕!这非常巧妙!!

请看以下代码示例:

struct ContentView: View {
    @State private var isActive: Bool = false

    var body: some View {
        NavigationView {
            NavigationLink(
                destination: SecondView(isActive: $isActive),
                isActive: $isActive,
                label: {
                    Text("Go to second View")
                })
                .navigationTitle("MainView")
        }
    }
}

我的第二个视图:
struct SecondView: View {
    @Binding var isActive: Bool

    var body: some View {
            NavigationLink("Go to Third View",destination:  ThirdView(isActive: $isActive))
                .navigationTitle("Second View")
    }
}


这里是展开按钮,但它可以在任何视图中。 设置 isActive = false 在这里起到了一些魔力!
struct ThirdView: View {
    @Binding var isActive: Bool

    var body: some View {
        Button("Unwind!"){
            isActive = false
        }
        .navigationTitle("Last View!")
    }
}

0

我也在寻找那个方法。
我采用了两次调用self.presentationMode.wrappedValue.dismiss()的方式,但它与取消事务的行为并不完全相同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接