3

The same code runs perfectly on iOS, and the behaviour is as expected where whenever the tabview selection is changed, the toolbar items are updated accordingly. On macOS, the toolbar items do not disappear.

Initial TabView

After selecting the other tab

import SwiftUI

struct ContentView: View {
    var body: some View {
        TabView {
            Text("Screen 1")
                .toolbar {
                    ToolbarItem {
                        Text("Item 1")
                    }
                }
                .tabItem {
                    Label("Home", systemImage: "house")
                }
            Text("Screen 2")
                .toolbar {
                    ToolbarItem {
                        Text("Item 2")
                    }
                }
                .tabItem {
                    Label("Explore", systemImage: "network")
                }
        }
    }
}

I tried going through all the docs, and I couldn't understand how to figure out this issue. My actual app actually has two different SplitNavigationViews as different items for TabViews, and this is the simplest view where this issue is reproducible.

Navan Chauhan
  • 397
  • 6
  • 14

1 Answers1

2

It must be something specific to your (actual) view hierarchy that is causing the behavior to differ between iOS and macOS, because when I tested your sample code, iOS also does not remove the toolbar item.

sample code and preview of iPadOS with duplicate toolbar items

My understanding is that .toolbar is meant to be composable — multiple views can add their own toolbar items without intending to remove/replace those of other views. It doesn't really make sense for TabView, but I can understand why they haven't tried to add hidden logic to have the system take care of that.

So instead, you can explicitly tell the system which toolbar items should be visible using conditionals and state.

enum Tabs: Hashable {
    case home
    case explore
}

struct ContentView: View {
    @State private var selectedTab = Tabs.home

    var body: some View {
        NavigationSplitView {
            List {
                Text("Lorem ipsum")
            }
        } detail: {
            TabView(selection: $selectedTab) {
                Text("Screen 1")
                    .tabItem {
                        Label("Home", systemImage: "house")
                    }
                    .tag(Tabs.home)
                Text("Screen 2")
                    .tabItem {
                        Label("Explore", systemImage: "network")
                    }
                    .tag(Tabs.explore)
            }
            .toolbar {
                switch selectedTab {
                    case .home:
                        ToolbarItem {
                            Text("Item 1")
                        }
                    case .explore:
                        ToolbarItem {
                            Text("Item 2")
                        }
                }
            }
        }
    }
}

new code and iPadOS preview with toolbar items behaving as requested

macOS app with toolbar items behaving as requested

Brock Batsell
  • 5,786
  • 1
  • 25
  • 27
  • I am not accepting this as the proper solution for a few reasons I will update this comment with tomorrow, but the answer is technically correct so I am awarding you the bounty – Navan Chauhan May 01 '23 at 04:54