0

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?

1
  • 1
    But the button in a ViewModifier Commented Mar 29, 2024 at 11:44

1 Answer 1

1

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(...)
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.