【问题标题】:SwiftUI: Involuntary navigation of NavigationLinkSwiftUI:NavigationLink 的非自愿导航
【发布时间】:2021-09-07 08:02:19
【问题描述】:

我有一个物品清单。当我单击一个项目 Show Alert 时,我会显示一个警报,其中显示两个选项:Navigate 关闭警报并导航到详细视图或 Cancel 应该只是关闭警报。

问题是Cancel 仍然使NavigationLink 导航。 有什么解决方案可以让第二个项目直接导航而其他项目显示允许您取消的警报。

这是一个最小的可重现示例:

struct ContentView: View {

    let items = ["1", "2", "3", "4"]

    var body: some View {
        NavigationView {
            List {
                ForEach(items, id: \.self) { item in
                    RowView(item: item)
                }
            }
        }
    }
}

struct RowView: View {

    let item: String

    @State private var isShowingNext = false
    @State private var isShowingAlert = false

    private var isShowingNextBinding: Binding<Bool> {
        Binding(
            get: {
                !isShowingAlert && isShowingNext
            }, set: {
                isShowingNext = $0
            }
        )
    }

    var body: some View {
        ZStack {
            if item != "2" {
                NavigationLink(
                    destination: Text("Hello"),
                    isActive: isShowingNextBinding,
                    label: {
                        Text(item)
                    }
                ).hidden()
                Button(
                    action: {
                        isShowingAlert.toggle()
                    }, label: {
                        Text("\(item) Show Alert First")
                    }
                )
                .alert(isPresented: $isShowingAlert) {
                    Alert(
                        title: Text("Alert")
                            .foregroundColor(Color.red)
                            .font(.title),
                        message: Text("Hello"),
                        primaryButton: .destructive(
                            Text("Navigate"),
                            action: {
                                isShowingNext = true
                            }
                        ),
                        secondaryButton: .cancel()
                    )
                }
            } else {
                NavigationLink(
                    destination: Text("Hello"),
                    isActive: isShowingNextBinding,
                    label: {
                        Text("\(item) Show Directly")
                    }
                )
            }
        }
    }
}

确保在 iOS 中运行它,因为在 watchOS 上它可以按预期工作。

【问题讨论】:

    标签: swift swiftui swiftui-navigationlink swiftui-navigationview


    【解决方案1】:

    只需更改您的“设置”部分,如下所示:

    Binding(
            get: {
                !isShowingAlert && isShowingNext
            }, set: {_ in
                isShowingNext = false
            }
        )
    

    我无法定义这个答案。我刚刚进行了实验,它的效果绝对符合您的预期(希望如此)。

    附:在 Xcode 版本 13.0 beta 5 中,它运行良好,无需更改“设置”

    【讨论】:

      【解决方案2】:

      将 RowView 更新为:

      struct RowView: View {
      
          let item: String
      
          @State private var isShowingNext = false
          @State private var isShowingAlert = false
      
          private var isShowingNextBinding: Binding<Bool> {
              Binding(
                  get: {
                      !isShowingAlert && isShowingNext
                  }, set: { _ in
                      isShowingNext = false
                  }
              )
          }
      
          var body: some View {
              ZStack {
                  if item != "2" {
                      NavigationLink(
                          destination: Text("Hello"),
                          isActive: isShowingNextBinding,
                          label: {
                              Text(item)
                          }
                      ).hidden()
                      Button(
                          action: {
                              isShowingAlert.toggle()
                          }, label: {
                              Text("\(item) Show Alert First")
                          }
                      )
                      .alert(isPresented: $isShowingAlert) {
                          Alert(
                              title: Text("Alert")
                                  .foregroundColor(Color.red)
                                  .font(.title),
                              message: Text("Hello"),
                              primaryButton: .destructive(
                                  Text("Navigate"),
                                  action: {
                                      isShowingNext = true
                                  }
                              ),
                              secondaryButton: .cancel()
                          )
                      }
                  } else {
                      NavigationLink(
                          destination: Text("Hello"),
                          isActive: $isShowingNext,
                          label: {
                              Text("\(item) Show Directly")
                          }
                      )
                  }
              }
          }
      }
      

      将 Binding 的设置器更新为始终更新为 false,并拥有一个单独的 NavigationLink,通过直接将 Binding 传递给 isShowingNext 来直接导航。

      这是一种解决方法,但它确实有效。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-07-20
        • 2013-06-20
        • 2020-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多