【问题标题】:How do you dismiss the detail view in SwiftUI on an iPad/split view layout?如何在 iPad/拆分视图布局上关闭 SwiftUI 中的详细视图?
【发布时间】:2022-01-25 07:55:58
【问题描述】:

我正在尝试关闭 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")
            }
        }
    }
}

这是一个演示问题的示例。按下关闭时,它会取消 iPhone 上关闭细节控制器的选择。在 iPad 上,它将详细视图保留在那里,而不是返回到空白视图。

这是选择项目之前的视图。您可以在右侧看到空白视图。

选择一个项目后,左侧被选中,右侧显示相应的详细视图。

在通过取消选择(或使用环境关闭)关闭视图后,左侧的选择会按原样消失,但右侧的详细视图保持不变。这应该已经消失了,空白视图应该再次显示。

【问题讨论】:

    标签: ios swift iphone ipad swiftui


    【解决方案1】:

    如果您愿意放弃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())
        }
    }
    

    【讨论】:

    • 遗憾的是我不愿意放弃分裂,这是问题的主要原因。堆栈导航有其用途,但我真的想要一个拆分视图。我有一个临时解决方案,如果没有其他人有更合适的方法,我会发布。不过,我很感激这个答案。
    【解决方案2】:

    我已经制定了一个可行的解决方案,但它需要一些额外的逻辑。它需要进行某种检查以查看数据是否存在,如果不存在则有条件地显示主视图或空白视图。

    这是我在问题中使用的示例修改后的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")
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多