首页 > 解决方案 > 带有 `isActive=true` 的嵌套 NavigationLinks 未正确显示

问题描述

我已经开始学习 SwiftUI,但是在构建我的 NavigationView 时遇到了一些问题 - 我不确定这是否是一个错误,或者我是否误解了嵌套导航链接应该如何工作!

这是我当前的代码:

import SwiftUI

struct ContentView: View {
  var body: some View {
    NavigationView {
      ViewOne()
    }
  }
}

struct ViewOne: View {
  @State var isActiveOne: Bool = true

  var body: some View {
    VStack {
      Text("View One")
      
      NavigationLink(
        destination: ViewTwo(),
        isActive: $isActiveOne,
        label: { EmptyView() }
      )
      
      Button(
        action: { self.isActiveOne = true },
        label: { Text("Set isActiveOne=true") }
      )
    }
  }
}

struct ViewTwo: View {
  @State var isActiveTwo: Bool = true

  var body: some View {
    VStack {
      Text("View Two")
      
      NavigationLink(
        destination: Text("Success!"),
        isActive: $isActiveTwo,
        label: { EmptyView() }
      )

      Button(
        action: { self.isActiveTwo = true },
        label: { Text("Set isActiveTwo=true") }
      )
    }
  }
}

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

我希望:

但是,当我在 iOS 14.5 模拟器上运行此代码时,第二个 NavigationLink 不会自动显示(我只看到 ViewTwo Button 文本)。

我还觉得奇怪的是,如果我默认 isActiveTrue 为 false,然后按下按钮,它会正确导航 - 默认“true”状态 + 嵌套导航链接的组合似乎导致了问题。

知道这是否是 SwiftUI 中的错误吗?还是我在这里的设置做错了什么?

任何想法都会有很大的帮助——我已经把头撞在墙上一段时间了......

预览截图

标签: swiftswiftuinavigation

解决方案


这看起来像一个错误,您可以在https://feedbackassistant.apple.com提交它

一个临时的解决方法是将你NavigationLink的 s 放在一个列表中。这似乎适用于 iOS 14.5 和 15(测试版 2)

隐形名单

如果您不想要列表行为/外观,那么您可以将列表放在背景上并使其透明(使用opacity修饰符)

以下是不可见列表解决方法的示例:

struct WorkaroundLink<Destination: View>: View {
    let destination: Destination
    let isActive: Binding<Bool>

    var body: some View {
        List {
            NavigationLink(
                destination: destination,
                isActive: isActive,
                label: { EmptyView() }
            )
        }.opacity(0.01)
    }
}

extension View {
    func workaroundLink<D: View>(to destination: D, isActive: Binding<Bool>) -> some View {
        background(WorkaroundLink(destination: destination, isActive: isActive))
    }
}

用这个结构重写你的例子变成:

struct ContentView: View {
    var body: some View {
        NavigationView { ViewOne() }
    }
}

struct ViewOne: View {
    @State var isActiveOne = true

    var body: some View {
        VStack {
            Text("View One")
            Button("Set isActiveOne=true") { isActiveOne = true }
        }.workaroundLink(to: ViewTwo(), isActive: $isActiveOne)
    }
}

struct ViewTwo: View {
    @State var isActiveTwo = true
    var body: some View {
        VStack {
            Text("View Two")

            Button(
                action: { self.isActiveTwo = true },
                label: { Text("Set isActiveTwo=true") }
            )
        }.workaroundLink(to: Text("Success!"), isActive: $isActiveTwo)
    }
}

推荐阅读