在 SwiftUI 中处理 NavigationView 内的 TabView 的最佳方法

Bou*_*ter 6 ios tabview swift navigationview swiftui

我正在使用 SwiftUI 开发 Swift 应用程序。

我有这样的设置,我将 TabView 放入 NavigationView 中,并在 tabView 上使用 navigationBarTitle。我这样做是因为如果我将 NavigationView 放入 TabView 中,当我转到 NavigationLink 时,我无法使 Tab 栏消失:目前看来对于 swiftUI 来说这是不可能的。

我的设置当前的问题是,由于我将 .navigationBarTitle 放在 TabView 上,因此当我更改选项卡视图时标题不会更改,并且由于某种原因无法重置子视图上的 .navigationBarTitle。

这是一个代码来解释我所说的:

内容视图:

NavigationView {
  TabView {
    SomeSubView().tabItem() { Text("SomeSubView") }
    Text("dummy2").tabItem() { Text("dummy2") }
    Text("dummy3").tabItem() { Text("dummy3") }
  }.navigationBarTitle("hello")
}
Run Code Online (Sandbox Code Playgroud)

一些子视图:

List(somearray) { element in
  NavigationLink(destination: elementDetails()) {
    SomeRowView()
  }
}
Run Code Online (Sandbox Code Playgroud)

这是预览(上面的代码不完全是我的代码,只是一个示例):

预览

现在我想将 .navigationBarTitle 放入 SomeSubView() 中,如下所示:

List(somearray) { element in
  NavigationLink(destination: elementDetails()) {
    SomeRowView()
  }
}.navigationBarTitle("title2")
Run Code Online (Sandbox Code Playgroud)

而不是为 TabView 选择全局标题。所以在这种情况下我会有类似的东西:

NavigationView {
  TabView {
    SomeSubView().tabItem() { Text("SomeSubView") }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后我在 SomeSubView() 内选择一个 .navigationBarTitle 但它不起作用(标题栏没有出现,而是选项卡标题被更改,这不是我想要的)。

所以我最终想出了这样的设置:

@State private var title = Text("Default_Title")

var body: some View {
  NavigationView {
    TabView {
      SomeSubView().tabItem { Text("SomeSubView") }.onAppear { self.title = Text("new_title") }
      Text("dummy2").tabItem { Text("dummy2") }
      Text("dummy3").tabItem { Text("dummy3") }
    }.navigationBarTitle(title)
  }
}
Run Code Online (Sandbox Code Playgroud)

这样,当我单击选项卡视图时,我可以动态更改标题,并且工作正常,但我还需要为每个选项卡视图设置不同的 .navigationBarItems,因此我对 .navigationBarItems 的前导和尾随参数做了同样的事情,例如这:

@State private var title = Text("Default_Title")
@State private var leading = NavBar_leading(type: "FirstView")
@State private var trailing = NavBar_trailing(type: "FirstView")

var body: some View {
  NavigationView {
    TabView {
      SomeSubView().tabItem { Text("SomeSubView") }.onAppear {
          self.title = Text("new_title")
          self.leading = NavBar_leading(type: "FirstView")
          self.trailing = NavBar_trailing(type: "FirstView")
      }
      Text("dummy2").tabItem { Text("dummy2") }
      Text("dummy3").tabItem { Text("dummy3") }
    }.navigationBarTitle(title).navigationBarItems(leading: leading, trailing: trailing)
  }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,我动态更新 .navigationBarItems 的前导和尾随参数,为每个选项卡视图设置不同的项目(在我的例子中为按钮)。NavBar_leading 和 NavBar_trailing 视图根据我传递的参数返回 Button 文本类型,如下所示:

struct NavBar_leading: View {
    var type: String
    
    var body: some View {
        if type == "FirstView" {
            return Button(action: {
                print("hello1 empty")
                }) {
                    Text("")
            }
        } else if (type == "SecondView") {
            return Button(action: {
                print("hello2")
                }) {
                    Text("SomeButton")
            }
        } else {
            return Button(action: {
                print("hello3 empty")
                }) {
                    Text("")
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在的问题是,我有时想从同一个 NavBar_leading 视图返回一个按钮文本,但有时返回一个按钮图像,但 Swift 不允许我从同一视图返回不同的类型。我认为按钮视图是一种类型,但似乎根据您放入的内容,它会变成另一种类型。

我听说 Any 视图类型在 Swift 中不是一个好的实践,并且会影响性​​能,所以我正在寻找一种方法来实现我想要的。

我解释了一切,因为我愿意接受任何其他建议,比如如果我能做得更好,我愿意从头开始,所以这是我的问题:

  • 我对 NavigationView 内的 TabView 的处理对于我需要做的事情来说是一个好主意吗?还有什么更好的事情是我不知道的吗?
  • 有没有其他方法可以为每个选项卡视图显示不同的标题,而不是像我一样更新的全局标题?
  • 有没有办法在不使用 Any 视图类型的情况下从视图返回不同的 Button 类型?我还能做些什么更好的事情吗?

谢谢