如何在iPad/拆分视图布局上关闭SwiftUI中的细节视图?

628mspwn  于 2023-11-16  发布在  Swift
关注(0)|答案(3)|浏览(161)

我试图在iPad上的主详细视图中关闭详细视图(例如,如果该项目在主视图中被删除,需要清空右侧)。

import SwiftUI

struct ContentView: View {
    @State var selection: String?
    
    var body: some View {
        NavigationView {
            List {
                NavigationLink(tag: "item1", selection: $selection) {
                    DetailView(item: "Item 1", selection: $selection)
                } label: {
                    Text("Item 1")
                }

                NavigationLink(tag: "item2", selection: $selection) {
                    DetailView(item: "Item 2", selection: $selection)
                } label: {
                    Text("Item 2")
                }
                
                NavigationLink(tag: "item3", selection: $selection) {
                    DetailView(item: "Item 3", selection: $selection)
                } label: {
                    Text("Item 3")
                }
            }
            
            Text("Blank View")
        }
    }
}

struct DetailView: View {
    let item: String
    @Binding var selection: String?
    
    @Environment(\.dismiss) var dismiss
    
    var body: some View {
        VStack {
            Text("Detail for \(item)")
            Button {
                selection = nil
//                dismiss()
            } label: {
                Text("Dismiss")
            }
        }
    }
}

字符串
这是一个演示这个问题的例子。当按下dismiss时,它会取消iPhone上关闭细节控制器的选择。在iPad上,它会保留细节视图,而不是返回到空白视图。
这是选择项目之前的视图。您可以在右侧看到空白视图。

选择项目后,将选择左手侧,右手侧将显示相应的详细视图。

在通过取消选择(或使用environment dismiss)关闭视图后,左边的选择会消失,但右边的细节视图会保持不变。这应该会消失,空白视图应该会再次显示。

ux6nzvsh

ux6nzvsh1#

我已经想出了一个解决方案,但它需要一些额外的逻辑。它需要某种检查,看看是否有数据,如果没有,然后有条件地显示主视图或空白视图。
下面是我在问题中使用的例子的修改后的DetailView。如果选择绑定为nil,则再次显示空白视图。

struct DetailView: View {
    let item: String
    @Binding var selection: String?
    
    var body: some View {
        if selection != nil {
            VStack {
                Text("Detail for \(item)")
                Button {
                    selection = nil
                } label: {
                    Text("Dismiss")
                }
            }
        } else {
            Text("Blank View")
        }
    }
}

字符串
NSManagedObject的情况下,你可以检查object.managedObjectContext != nil。我决定把它作为一个扩展,使之更容易。

extension View {
    
    @ViewBuilder
    public func blankWithoutContext<BlankView>(_ object: NSManagedObject, blankView: () -> BlankView) -> some View where BlankView: View {
        if object.managedObjectContext != nil {
            self
        } else {
            blankView()
        }
    }
}


它的用法是这样的:

MyView()
    .blankWithoutContext(object) {
        Text("Blank View")
    }

dxxyhpgq

dxxyhpgq2#

如果你愿意给予splitView(在侧边栏上有项目),你可以覆盖默认的导航设置,使其表现得像在iPhone上一样(使用堆叠导航视图),然后取消按钮就可以正常工作了。将这个修改器.navigationViewStyle(StackNavigationViewStyle())添加到NavigationView

struct ContentView: View {
    @State var selection: String?
    
    var body: some View {
        NavigationView {
            List {
                NavigationLink(tag: "item1", selection: $selection) {
                    DetailView(item: "Item 1", selection: $selection)
                } label: {
                    Text("Item 1")
                }

                NavigationLink(tag: "item2", selection: $selection) {
                    DetailView(item: "Item 2", selection: $selection)
                } label: {
                    Text("Item 2")
                }
                
                NavigationLink(tag: "item3", selection: $selection) {
                    DetailView(item: "Item 3", selection: $selection)
                } label: {
                    Text("Item 3")
                }
            }
            
            Text("Blank View")
        }
        .navigationViewStyle(StackNavigationViewStyle())
    }
}

字符串


的数据


jmp7cifd

jmp7cifd3#

对我来说,工作是这样的:我使用Listselection参数,而不是NavigationLink。当我需要弹出时,我将selection设置回nil。我想你可以在子视图中使用@Binding var selection来设置它。我在视图模型中有我的,因为我需要它在那里。

相关问题