Learn Courses My Dashboard

Having issues with NavigationLinks

I am having a rather strange issue trying to create a custom navigation bar for an iPad app that I am developing. The model in which I generate the options for the navigation bar is called HomeViewModel and here is how it looks like:

import Foundation
import SwiftUI

enum HomeTabs {
    case Restaurants
    case Minibar
    case Spa
    case Recreation
    case KidsClub
    case DiveCenter
    case ResortMap
    case More
}

struct HomeNavTabInfo: Identifiable {
    var id = UUID()
    var view: HomeTabs
    var icon: String
    var selectedIcon: String
    var name: String
}


class HomeViewModel: ObservableObject {
    @Published var HomeNavTabs = [HomeNavTabInfo]()
    @Published var selectedTab = HomeTabs.Restaurants
    @Published var vakkaruGray = Color(.sRGB, red: 191/255, green: 184/255, blue: 175/255, opacity: 1)
    
    init(){
        self.HomeNavTabs.append(HomeNavTabInfo(view: .Restaurants, icon: "icon_rest", selectedIcon: "icon_restp", name: "Restaurant"))
        self.HomeNavTabs.append(HomeNavTabInfo(view: .Minibar, icon: "icon_minib", selectedIcon: "icon_minibp", name: "Minibar"))
        self.HomeNavTabs.append(HomeNavTabInfo(view: .Spa, icon: "icon_spa", selectedIcon: "icon_spap", name: "Spa"))
        self.HomeNavTabs.append(HomeNavTabInfo(view: .Recreation, icon: "icon_rec", selectedIcon: "icon_recp", name: "Recreation"))
        self.HomeNavTabs.append(HomeNavTabInfo(view: .KidsClub, icon: "icon_kid", selectedIcon: "icon_kidp", name: "KidsClub"))
        self.HomeNavTabs.append(HomeNavTabInfo(view: .DiveCenter, icon: "icon_dive", selectedIcon: "icon_divep", name: "DiveCenter"))
        self.HomeNavTabs.append(HomeNavTabInfo(view: .ResortMap, icon: "icon_map", selectedIcon: "icon_mapp", name: "ResortMap"))
        self.HomeNavTabs.append(HomeNavTabInfo(view: .More, icon: "icon_more", selectedIcon: "icon_morep", name: "More"))
    }
}

At a later stage I do plan to use an external API to fetch the options that I am adding manually over here within init, perhaps stating that would give more sense why I am generating the options for the nav bar in this manner.

Now lets look at the views. To keep things clean I have 3 views aiding each other for the view that has this navigation bar - which is HomeView, HomeContent and HomeMainNavBar.

HomeView:

import SwiftUI

struct HomeView: View {
    var body: some View {
        NavigationView{
            ZStack {
                // MARK: bacground Image
                Image("background")
                    .resizable()
                    .scaledToFill()
                    .ignoresSafeArea()

                // MARK: Main Content
                HomeContent()
            }
        }
        .navigationViewStyle(.stack)
    }
}

HomeContent:

import SwiftUI

struct HomeContent: View {
    @EnvironmentObject var HomeModel: HomeViewModel
    var body: some View {
        GeometryReader { proxy in
            VStack  {
                // MARK: LOGO
                Image("logo white")
                    .padding(.vertical, 30)
                
                Spacer()
                
                // MARK: Navigation - Header
                Text("OUR DINNING & EXPERIENCES")
                    .font(Font.custom("Lato-Bold", size:30))
                    .foregroundColor(.white)
                
                // MARK: Navigation - Bar
                HomeMainNavBar(navBarWidth: proxy.size.width * 80/100)
                
                // MARK: Footer
                Text("For assistance contact your butler or our guest service center via 0")
                    .font(Font.custom("Lato-BoldItalic", size: 18))
                    .foregroundColor(.white)
                    .padding(.vertical, 20)
            }
            .frame(width: proxy.size.width)
        }
    }
}

HomeMainNavBar:

import SwiftUI

struct HomeMainNavBar: View {
    @EnvironmentObject var HomeModel: HomeViewModel
    
    var navBarWidth: CGFloat
    
    var body: some View {
        
        VStack {
            Rectangle()
                .fill(HomeModel.vakkaruGray)
                .frame(height: 5)
            
            // MARK: Navigation - Buttons
            
            HStack{
                ForEach (HomeModel.HomeNavTabs) { tab in
                    NavigationLink {
                        SecondScreenView()
                    } label: {
                        Image(HomeModel.selectedTab == tab.view ? tab.selectedIcon : tab.icon)
                            .resizable()
                            .scaledToFit()
                            .frame(height: 125)
                            .onTapGesture {
                                HomeModel.selectedTab = tab.view
                            }
                    }
                }
                
                NavigationLink {
                    SecondScreenView()
                } label: {
                    Image("icon_rest")
                        .resizable()
                        .scaledToFit()
                        .frame(height: 125)
                }
            }
            
            
            Spacer()
            Rectangle()
                .fill(HomeModel.vakkaruGray)
                .frame(height: 5)
        }
        .frame(width: navBarWidth,height: 150)
        
    }
}

Here as you could see I am using a ForEach loop to create the options/Navigation Links within the Horizontal Stack. When these links are pressed it does not navigate to the SecondScreenView() - here SecondScreenView is just a basic screen with a Text element on it, nothing fancy. However I also noticed that if I create a NavigationLink out of the ForEach loop, this particular navigation link which is out of the ForEach loop works and when once pressed it navigates to SecondScreenView just as expected.

I am not sure where and what I am doing wrong and how to fix it, any assistance will be much appreciated. As mentioned earlier I do require to generate these options programatically according to the response from the API i.e. I need to be able to loop through the HomeNavTabInfo to create the Navigation Links.

Looking forward to a quick and favorable response.

I figured where the issue was, in my original code for the nav links I had included a onTapGesture modifier, which initially I had created to be able to identify which button has been clicked by updating a published property called selectedTab. Removing this modifier navigation is working as expected. However now I need to find a way to be able to know which button has been clicked to navigate to SecondScreenView and I guess instead of using the approach I had used initally I will need to use binding and selection modifier on the navigation link to avoid the original issue. If you could advise on a better solution I am open to listen.