与确认对话框或警报交互会导致父视图弹出

x4shl7ld  于 2022-10-23  发布在  Swift
关注(0)|答案(2)|浏览(153)

当您导航并打开确认对话框时。当您选择是、否或取消时,应用程序所在的页面将被取消,它会将您带回上一页的表单。
我们还发现,警报也会发生这种情况。
这是一个足够简单的应用程序结构,顶层标签,然后是一个链接到子页面的菜单。
以下是该漏洞的快速演示:

我们制作了一个示例应用程序来演示这一点。我们如何在保持应用程序结构的同时防止这种情况发生?

import SwiftUI

@main
struct testApp: App {
    var body: some Scene {
        WindowGroup {
            NavigationView {
                TabView() {
                    Form {
                        NavigationLink(destination: SubPage()) {
                            Image(systemName: "clock")
                            Text("Sub Page")
                        }
                        // This is where more menu options would be
                    }
                    .tag(1)
                    .tabItem {
                        Image(systemName: "square.grid.2x2")
                        Text("Tab 1")
                    }
                    // This is where more tab pages would be
                }
            }
        }
    }
}

struct SubPage: View {
    @State private var confirmDialogVisible = false

    var body: some View {
        VStack {
            Button{
                confirmDialogVisible = true
            } label: {
                Text("popup")
            }
        }
        .confirmationDialog("Confirm?", isPresented: $confirmDialogVisible) {
            Button("Yes") {
                print("yes")
            }
            Button("No", role: .destructive) {
                print("no")
            }
        }
    }
}

我们使用的是XCode 14.1,在iOS 16.1上运行

nom7f22z

nom7f22z1#

我通常使用ViewModifer来保持选项卡之间的一致性。一个修饰符用于选项卡的根,一个修饰符用于子项。

///Modifier that uses `ToolbarViewModifier` and includes a `NavigationView`
struct NavigationViewModifier: ViewModifier{
    func body(content: Content) -> some View {
        NavigationView{
            content
                .modifier(ToolbarViewModifier())
        }
    }
}
///`toolbar` that can be used by the root view of the navigation
///and the children of the navigation
struct ToolbarViewModifier: ViewModifier{
    let title: String = "Company Name"
    func body(content: Content) -> some View {
        content
            .toolbar {
                ToolbarItem(placement: .principal) {
                    VStack{
                        Image(systemName: "sparkles")
                        Text(title)
                    }
                }
            }
    }
}

然后视图使用它,就像这样。

import SwiftUI

struct CustomTabView: View {
    var body: some View {
        TabView{
            ForEach(0..<4){ n in
                CustomChildView(title: n.description)
                    //Each tab gets a `NavigationView` and the shared toolbar
                    .modifier(NavigationViewModifier())
                    .tabItem {
                        Text(n.description)
                    }
            }
        }
    }
}
struct CustomChildView: View {
    let title: String
    @State private var showConfirmation: Bool = false
    var body: some View {
        VStack{
            Text(title)

            NavigationLink {
                CustomChildView(title: "\(title) :: \(UUID().uuidString)")
            } label: {
                Text("open child")
            }
            Button("show confirmation") {
                showConfirmation.toggle()
            }
            .confirmationDialog("Confirm?", isPresented: $showConfirmation) {
                Button("Yes") {
                    print("yes")
                }
                Button("No", role: .destructive) {
                    print("no")
                }
            }
        }
        //Each child uses the shared toolbar
        .modifier(ToolbarViewModifier())

    }
}

我坚持使用NavigationView,因为这就是您的代码中的内容,但是如果我们考虑到新的NavigationStack,这两个修饰符的可能性就会成倍增加。
您可以包括仅在路径不为空、从任何位置返回到根目录等情况下才显示的自定义后退按钮。
苹果公司表示,
选项卡栏使用栏项目在同一视图中内容的互斥窗格之间导航
确保当用户导航到应用程序中的不同区域时,选项卡栏可见
https://developer.apple.com/design/human-interface-guidelines/components/navigation-and-search/tab-bars/
NavigationViewNavigationStack放在顶部是违反这些准则的,因此是无休止错误的来源,特别是当你考虑到iPadOS的时候。

c6ubokkw

c6ubokkw2#

简单的解决方案是使用navigationDestination

struct testApp: App {

    @State var goToSubPage = false

    var body: some Scene {
        WindowGroup {
            NavigationStack {
                TabView() {
                    Form {
                        VStack {
                            Image(systemName: "clock")
                            Text("Sub Page")
                        }
                        .onTapGesture {
                            goToSubPage = true
                        }
                        // This is where more menu options would be
                    }
                    .navigationDestination(isPresented: $goToSubPage, destination: {
                        SubPage()
                    })
                    .tag(1)
                    .tabItem {
                        Image(systemName: "square.grid.2x2")
                        Text("Tab 1")
                    }
                    // This is where more tab pages would be
                }
            }
        }
    }
}

我测试了一下,它再也不会自己弹出来了。

相关问题