I'm setting up an SwiftUI app with TabView-navigation and individual NavigationStacks (to preserve individual navigation state per stack).
One thing that buggles my mind is that I want to have the same profile button in the top right navigationbar on every View. Adding the navigationbar item as below requires me to have the exact same code/addition in every View.
.navigationDestination(isPresented: $presentProfilePage) {
ProfileView()
}
.toolbar {
Button {
presentProfilePage = true
} label: {
if let img = user.displayImg {
Image(uiImage: img)
.resizable()
.frame(width: 48, height: 48)
} else {
Image.defaultProfileImage
}
}
}
Is there a way to set the navigationbar items once and then they are visible on all views?
You can put this code in a ViewModifier
. You can put presentProfilePage
as a @State
in there.
struct ProfileNavigation: ViewModifier {
@State var presentProfilePage = false
let image: UIImage?
func body(content: Content) -> some View {
content
.navigationDestination(isPresented: $presentProfilePage) {
ProfileView()
}
.toolbar {
Button {
presentProfilePage = true
} label: {
if let image {
Image(uiImage: image)
.resizable()
.frame(width: 48, height: 48)
} else {
Image.defaultProfileImage
}
}
}
}
}
extension View {
func profileNavigation(image: UIImage?) -> some View {
modifier(ProfileNavigation(image: image))
}
}
You'd just add .profileNavigation(...)
to each view you want to have this button.
Alternatively, you can use a NavigationLink
in the toolbar
directly. You would just extract the NavigationLink
as a View
to reuse it:
struct ProfileNavigation: View {
let image: UIImage?
var body: some View {
NavigationLink {
ProfileView()
} label: {
if let image {
Image(uiImage: image)
.resizable()
.frame(width: 48, height: 48)
} else {
Image.defaultProfileImage
}
}
}
}
Usage:
.toolbar {
ProfileNavigation(...)
}