TechnologiesSwiftUI

ToolbarPlacement struct

iOSmacOStvOSwatchOSvisionOSiOS 16.0+✓ renders

The placement of a toolbar.

How it works

ToolbarPlacement names a region of the interface where a toolbar lives — the navigation bar, the bottom bar, the tab bar, or the window toolbar — so you can talk about that region by name rather than positioning controls yourself. You reach for it whenever a modifier needs to know *which* bar it acts on: showing or hiding a bar, recoloring its background, or choosing where toolbar content lands. It turns an otherwise ambiguous instruction like "hide the toolbar" into a precise one — hide *this* bar, leave the others alone.

  1. Refer to a bar by its placement value

    ToolbarPlacement exposes the standard bars as static members you pass wherever a placement is expected. The example targets two of them: .navigationBar, the bar tied to the navigation title, and .bottomBar, the bar that sits at the bottom of the screen. Each value identifies a region without you computing any coordinates.

  2. Pass the placement to toolbar(_:for:)

    The for: parameter of the .toolbar(_:for:) modifier takes a ToolbarPlacement, scoping the visibility change to just that bar. In the example, .toolbar(.visible, for: .navigationBar) and .toolbar(.hidden, for: .bottomBar) each apply to one named region, so the navigation bar and the bottom bar are controlled independently.

  3. Combine the placement with a Visibility

    The first argument is a Visibility.visible, .hidden, or .automatic — and the ToolbarPlacement in for: decides who it applies to. Pairing .visible with .navigationBar keeps the title bar on screen, while pairing .hidden with .bottomBar removes the bottom bar; swap either side and the same placement reads differently.

  4. Stack modifiers to address several bars

    Because each .toolbar(_:for:) call carries its own ToolbarPlacement, you chain one modifier per bar you want to affect. The example chains two calls on the List so the .navigationBar and .bottomBar placements are set in the same pass, leaving any other bar at its default behavior.

  5. Provide a context that owns the bar

    A placement only resolves to a real region when an enclosing container actually presents that bar. Here the NavigationStack plus .navigationTitle("Mail") is what gives .navigationBar something to show; without such a host, a ToolbarPlacement has no bar to point at.

Try it — Change .toolbar(.visible, for: .navigationBar) to .toolbar(.hidden, for: .navigationBar) and watch the title bar disappear while the .bottomBar rule stays untouched — proof that each ToolbarPlacement is addressed on its own.

Example & preview

Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.

ToolbarPlacement.swift
struct ToolbarPlacementDemo: View {
    var body: some View {
        NavigationStack {
            List {
                Text("Inbox")
                Text("Drafts")
                Text("Sent")
            }
            .navigationTitle("Mail")
            .toolbar(.visible, for: .navigationBar)
            .toolbar(.hidden, for: .bottomBar)
        }
    }
}
Live preview
Inbox Drafts Sent 9:41 Mail
Inbox Drafts Sent 9:41 Mail
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →