Home > database >  NavigationLink problem when using it in a ForEach
NavigationLink problem when using it in a ForEach

Time:09-11

I am building an app which displays a planning of matches. Each day containing at least one match create a group with the date and the matches. Those matches are embedded in a NavigationLink to access to a detail view. Here an example of the layout

The issue occurs when I click on a match that is part of a day with multiple matches. After having clicked on a match, a message appears in the console "SwiftUI encountered an issue when pushing aNavigationLink. Please file a bug." and it shows me the destination view. But when I go back to the root view, I can't click on any matches.

If I click on a match in a day with only one match, I can click on other matches.

Here is my code :

PlanningMatchView :

ZStack() {
    HStack() {
        Image(systemName: "testtube.2")
        Spacer()
        Image(systemName: "testtube.2")
        Text("Match \(id)")
            .foregroundColor(.white)
        Image(systemName: "testtube.2")
        Spacer()
    }
    .padding(.init(top: 0, leading: 15, bottom: 0, trailing: 15))
}
.frame(height: 50)
.background(matchBackgroundColor)

PlanningDayView :

VStack(alignment: .center, spacing: 0) {
    HStack {
        Text(jour.date)
            .bold()
            .foregroundColor(.white)
            .frame(height: 50)
        .background(.clear)
        Spacer()
    }
    .padding(.leading, 12)
    Divider()
        .frame(height: 1)
        .overlay(lineColor)
    ForEach(jour.matches, id: \.self) { match in
        ZStack {
            NavigationLink(destination: MatchDetailView(matchId: match.id)) {
                PlanningMatchView(id: match.id, hour: match.hour, game: match.game, team1: match.team1, team2: match.team2)
            }
            .padding(.init(top: 0, leading: 0, bottom: 0, trailing: 15))
        }
        Divider()
            .frame(width: 300, height: 0.5)
            .overlay(lineColor)
    }
}
.background(matchBackgroundColor)
.cornerRadius(7)
.listRowBackground(Color.clear)
.listRowSeparator(.hidden)
.padding(.init(top: 0, leading: 0, bottom: 8, trailing: 0))

HomeView : for now I'm taking the matches from a Match array

NavigationView {
    ZStack {
        Color("backgroundColor").edgesIgnoringSafeArea(.all)
        List {
            PlanningDayView(jour: Jour(date: "Mercredi 23 juillet", matches: [Matches[1]]))
            PlanningDayView(jour: Jour(date: "Dimanche 27 juillet", matches: [Matches[2], Matches[3]]))
            PlanningDayView(jour: Jour(date: "Mercredi 30 juillet", matches: [Matches[4]]))
            PlanningDayView(jour: Jour(date: "Mardi 02 août ", matches: [Matches[5], Matches[6]]))
            PlanningDayView(jour: Jour(date: "Mardi 09 août", matches: [Matches[7]]))
            PlanningDayView(jour: Jour(date: "Jeudi 11 août", matches: [Matches[1], Matches[2]]))
        }
        .listStyle(PlainListStyle())
        .navigationTitle("Planning")
        .foregroundColor(.white)
    }
}

ContentView :

var body: some View {
    TabView {
        HomeView()
            .tabItem {
                Image("planning.unselected")
                    .renderingMode(.template)
                Text("Planning")
            }
        RankView()
            .tabItem {
                Image("classement")
                    .renderingMode(.template)
                Text("Classement")
            }
    }
}

I hope I've been clear in all my explanations.

CodePudding user response:

That's not really how List works. A List is separated into Sections and Rows but you are treating a row like a section and making the PlanningDayView with custom rows and dividers.

Therefore each PlanningDayView is a single row, but a NavigationLink always takes the entire row so multiple are not possible.

You have two options:

  1. Go the List way and simply remove a lot of the custom handling you currently have
  2. Keep the custom handling, but then you shouldn't use List but a ScrollView

This would be a minimal List way of what you are trying to do I think. I restructured the PlanningDayView into a Section. Then each NavigationLink is a separate row and therefore works just as expected.

struct PlanningDayView: View {
    let jour: Jour
        
    var body: some View {
        Section {
            Text(jour.date)
                .bold()
                .foregroundColor(.white)
            
            ForEach(jour.matches, id: \.self) { match in
                NavigationLink {
                    MatchDetailView(matchId: match.id)
                } label: {
                    PlanningMatchView(id: match.id,
                                      hour: match.hour,
                                      game: match.game,
                                      team1: match.team1,
                                      team2: match.team2)
                }
            }
        }
        .listRowBackground(matchBackgroundColor)
        .listRowSeparatorTint(lineColor)
    }
}

Instead of .listStyle(PlainListStyle()) on your HomeView you would need to change it to .listStyle(.insetGrouped) to regain the rounded corner styling you currently have

CodePudding user response:

replace your List in HomeView, with ScrollView, works for me.

  • Related