My first view has a NavigationView with a Tab Bar View
struct TestView: View {
var body: some View {
NavigationView {
TabTestView()
}
}
}
In the Tab Bar, I have two views, say TestView1 and TestView2.
struct TabTestView: View {
var body: some View {
TabView {
TestView1()
.tabItem {
Label("Test 1", systemImage: "list.dash")
}
TestView2()
.tabItem {
Label("Test 2", systemImage: "plus")
}
}
}
}
I now need to add a toolbar button to TestView1. Here is my attempt to do so:
struct TestView1: View {
var body: some View {
Text("Hello World")
.navigationTitle("Test View 1")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Save") {
print("Toolbar button click")
}
}
}
}
}
While this adds the Navigation Title to the page, the toolbar button is not added, as shown in the screenshot below:
If I, however, add the toolbar to the TabTestView, as below, the toolbar button does show up.
struct TabTestView: View {
var body: some View {
TabView {
TestView1()
.tabItem {
Label("Test 1", systemImage: "list.dash")
}
TestView2()
.tabItem {
Label("Test 2", systemImage: "plus")
}
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Save") {
print("Toolbar button click")
}
}
}
}
}
This is a problem - the code to be executed on the button click depends upon variables in TestView1, and adding the toolbar to the TabTestView doesn't feel right, semantically the toolbar "belongs" in TestView1.
Any thoughts would be greatly appreciated.
Update December 20, 2024:
Apple responded to my feedback, FB9727010. It was a bug, and it is now fixed in iOS 18.2. I verified on the MRE app I sent with the report, and it works for both NavigationView
and NavigationStack
.
Once I had working code, I realized I had seen this before. It appears to be a bug in SwiftUI. TabView
and NavigationView
don't play well together. You will find a lot of my answer will say one NavigationViews
at the top of the view hierarchy, which is what you have done. That will not work in this instance. The workaround is to put a NavigationViews
in each of the views in the tabs separately for this to work. You will still get all of the correct NavigationViews
behavior for each of those hierarchies, but it is duplicative. I don't think I ever filed a Radar on it, but I will today and will post the Radar number here.
struct TestView: View {
var body: some View {
// NavigationView { //Remove this NavigationView
TabTestView()
// }
}
}
struct TabTestView: View {
var body: some View {
TabView {
TestView1()
.tabItem {
Label("Test 1", systemImage: "list.dash")
}
TestView2()
.tabItem {
Label("Test 2", systemImage: "plus")
}
}
}
}
struct TestView1: View {
var body: some View {
NavigationView { // Add here
Text("Hello World 1")
.navigationTitle("Test View 1")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Save") {
print("Toolbar button click")
}
}
}
}
}
}
struct TestView2: View {
var body: some View {
NavigationView { // Add here
Text("Hello World 2")
.navigationTitle("Test View 2")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Save") {
print("Toolbar button click")
}
}
}
}
}
}
The Radar number is FB9727010.