Too many entries for NavigationStack

Hi there,

I am currently programming an app for certain medication usage for paramedics in my region. For that, I made a List inside a NavigationStack with NavigationLinks to further Swift files, each one for one drug. The problem is, that when I add more than 16 NavigationLinks to the NavigationStack, the app stops working and crashes. Is it too much code or do I have to do anything else? I am very new to programming in general so I would love to hear from you!

Greetings Laurin

Here is the code:

//
//  Medikamente.swift
//  SAA Medikamente
//
//  Created by Laurin Bräunig on 18.10.23.
//

import SwiftUI

struct Medikamente: View {
    var body: some View {
        
// Medikamentenliste
        
        NavigationStack {
//Medikamente
            
            List {
                NavigationLink(destination: Acetylsalicylsaeure()){
                    Text("Acetylsalicylsäure")
                }
                NavigationLink(destination: Amiodaron()){
                    Text("Amiodaron")
                }
                NavigationLink(destination: Atropin()){
                    Text("Atropin")
                }
                NavigationLink(destination: Butylscopolamin()){
                    Text("Butylscopolamin")
                }
                NavigationLink(destination: Dimenhydrinat()){
                    Text("Dimenhydrinat")
                }
                NavigationLink(destination: Dimentinden()){
                    Text("Dimentinden")
                }
                NavigationLink(destination: Epinephrin()){
                    Text("Epinephrin")
                }
                NavigationLink(destination: Esketamin()){
                    Text("Esketamin")
                }
                NavigationLink(destination: Furosemid()){
                    Text("Furosemid")
                }
                NavigationLink(destination: Glucagon()){
                    Text("Glucagon")
                }
                NavigationLink(destination: Glucose()){
                    Text("Glucose")
                }
                NavigationLink(destination: Glyceroltrinitrat()){
                    Text("Glyceroltrinitrat")
                }
                NavigationLink(destination: Heparin()){
                    Text("Heparin")
                }
                NavigationLink(destination: Ibuprofen()){
                    Text("Ibuprofen")
                }
                NavigationLink(destination: Ipratropiumbromid()){
                    Text("Ipratropiumbromid")
                }
                NavigationLink(destination: Lidocain()){
                    Text("Lidocain")
                }
                
                
                
                .navigationTitle("Medikamente")
                .navigationBarTitleDisplayMode(.automatic)
                
            }
            
        }
    }
}

#Preview {
    Medikamente()
}

Thanks again for your help!

Answered by WeagleWeagle in 769335022

If you have multiple NavigationStacks and detailed descriptions for medications, and you need to link to details from other pages, you can still organize your code to avoid SwiftUI's NavigationLink limitation. Here's a way to achieve this:

  1. Use a ViewModel: Create a ViewModel that holds information about each medication, including its name and detailed description.
struct MedicationViewModel: Identifiable {
    let id = UUID()
    let name: String
    let detailedDescription: String

    // Add any other properties you need for each medication
}
  1. Create a Centralized Medication Data Source: Have a central data source that contains all the medication information. This data source can be an ObservableObject that you can pass around to different views in your app.
class MedicationDataSource: ObservableObject {
    @Published var medications: [MedicationViewModel] = []

    init() {
        // Initialize medications with data
        medications = [
            MedicationViewModel(name: "Acetylsalicylsäure", detailedDescription: "Details for Acetylsalicylsäure"),
            MedicationViewModel(name: "Amiodaron", detailedDescription: "Details for Amiodaron"),
            // Add more medications and descriptions here
        ]
    }
}
  1. Use NavigationLink in a Central View: In your central view, such as your Medikamente view, use a List or other UI element to display the medication names and create NavigationLinks to navigate to the detailed views.
struct Medikamente: View {
    @ObservedObject var dataSource = MedicationDataSource()

    var body: some View {
        NavigationView {
            List(dataSource.medications) { medication in
                NavigationLink(destination: MedicationDetailView(medication: medication)) {
                    Text(medication.name)
                }
            }
            .navigationTitle("Medikamente")
        }
    }
}
  1. Create Detailed Views: For each medication, create a detailed view (MedicationDetailView) that takes the MedicationViewModel as a parameter and displays the detailed information.
struct MedicationDetailView: View {
    let medication: MedicationViewModel

    var body: some View {
        VStack {
            Text(medication.name)
            Text(medication.detailedDescription)
            // Add more content as needed
        }
        .navigationTitle("Details")
    }
}

With this approach, you can easily add as many medications as you need without hitting SwiftUI's NavigationLink limitation. You can also navigate to detailed views from various pages in your app by sharing the MedicationDataSource. This centralizes your data and makes it more maintainable as your app grows.

You should try to use Group to reduce the number of subviews in a given view:

   List {
        Group {
                NavigationLink(destination: Acetylsalicylsaeure()){
                    Text("Acetylsalicylsäure")
                }
                NavigationLink(destination: Amiodaron()){
                    Text("Amiodaron")
                }
                NavigationLink(destination: Atropin()){
                    Text("Atropin")
                }
                NavigationLink(destination: Butylscopolamin()){
                    Text("Butylscopolamin")
                }
                NavigationLink(destination: Dimenhydrinat()){
                    Text("Dimenhydrinat")
                }
                NavigationLink(destination: Dimentinden()){
                    Text("Dimentinden")
                }
                NavigationLink(destination: Epinephrin()){
                    Text("Epinephrin")
                }
                NavigationLink(destination: Esketamin()){
                    Text("Esketamin")
                }
        }

       Group {
                NavigationLink(destination: Furosemid()){
                    Text("Furosemid")
                }
                NavigationLink(destination: Glucagon()){
                    Text("Glucagon")
                }
                NavigationLink(destination: Glucose()){
                    Text("Glucose")
                }
                NavigationLink(destination: Glyceroltrinitrat()){
                    Text("Glyceroltrinitrat")
                }
                NavigationLink(destination: Heparin()){
                    Text("Heparin")
                }
                NavigationLink(destination: Ibuprofen()){
                    Text("Ibuprofen")
                }
                NavigationLink(destination: Ipratropiumbromid()){
                    Text("Ipratropiumbromid")
                }
                NavigationLink(destination: Lidocain()){
                    Text("Lidocain")
                }
          }

The issue you're facing where the app crashes after adding more than 16 NavigationLinks to a NavigationStack is likely related to a SwiftUI limitation known as the "10-View Limit." SwiftUI imposes a limit on the number of NavigationLink views that can be placed in a single navigation stack, which is usually around 10 to 16, depending on the device and iOS version.

To work around this limitation, you can consider organizing your medication list differently. Instead of creating a separate view for each medication and using NavigationLinks, you can create a dynamic list of medications using a ForEach loop and then pass the selected medication to a detail view when tapped. Here's an example of how you can do that:

struct Medication: Identifiable {
    let id = UUID()
    let name: String
    // Add any other properties you need for each medication
}

struct Medikamente: View {
    let medications: [Medication] = [
        Medication(name: "Acetylsalicylsäure"),
        Medication(name: "Amiodaron"),
        Medication(name: "Atropin"),
        // Add more medications here
    ]

    @State private var selectedMedication: Medication? = nil

    var body: some View {
        NavigationView {
            List(medications) { medication in
                Button(action: {
                    selectedMedication = medication
                }) {
                    Text(medication.name)
                }
            }
            .sheet(item: $selectedMedication) { medication in
                MedicationDetailView(medication: medication)
            }
            .navigationTitle("Medikamente")
        }
    }
}

struct MedicationDetailView: View {
    let medication: Medication

    var body: some View {
        // Create a detailed view for the selected medication
        Text("Details for \(medication.name)")
        // Add more content as needed
    }
}

In this example, we create a list of medications using a ForEach loop and use a @State variable to track the selected medication. When a medication is tapped, we display a detail view for that medication using the .sheet modifier.

This approach should allow you to display a list of medications without hitting the limitation imposed by SwiftUI's NavigationLink behavior.

Thanks for your answers!

@WeagleWeagle That would be a good Idea, unfortunately I have even more NavigationStacks in the detailed description of the medications. Any idea how I could fix that? I need to Link the details from other pages aswell. Thank you so much! Laurin

Accepted Answer

If you have multiple NavigationStacks and detailed descriptions for medications, and you need to link to details from other pages, you can still organize your code to avoid SwiftUI's NavigationLink limitation. Here's a way to achieve this:

  1. Use a ViewModel: Create a ViewModel that holds information about each medication, including its name and detailed description.
struct MedicationViewModel: Identifiable {
    let id = UUID()
    let name: String
    let detailedDescription: String

    // Add any other properties you need for each medication
}
  1. Create a Centralized Medication Data Source: Have a central data source that contains all the medication information. This data source can be an ObservableObject that you can pass around to different views in your app.
class MedicationDataSource: ObservableObject {
    @Published var medications: [MedicationViewModel] = []

    init() {
        // Initialize medications with data
        medications = [
            MedicationViewModel(name: "Acetylsalicylsäure", detailedDescription: "Details for Acetylsalicylsäure"),
            MedicationViewModel(name: "Amiodaron", detailedDescription: "Details for Amiodaron"),
            // Add more medications and descriptions here
        ]
    }
}
  1. Use NavigationLink in a Central View: In your central view, such as your Medikamente view, use a List or other UI element to display the medication names and create NavigationLinks to navigate to the detailed views.
struct Medikamente: View {
    @ObservedObject var dataSource = MedicationDataSource()

    var body: some View {
        NavigationView {
            List(dataSource.medications) { medication in
                NavigationLink(destination: MedicationDetailView(medication: medication)) {
                    Text(medication.name)
                }
            }
            .navigationTitle("Medikamente")
        }
    }
}
  1. Create Detailed Views: For each medication, create a detailed view (MedicationDetailView) that takes the MedicationViewModel as a parameter and displays the detailed information.
struct MedicationDetailView: View {
    let medication: MedicationViewModel

    var body: some View {
        VStack {
            Text(medication.name)
            Text(medication.detailedDescription)
            // Add more content as needed
        }
        .navigationTitle("Details")
    }
}

With this approach, you can easily add as many medications as you need without hitting SwiftUI's NavigationLink limitation. You can also navigate to detailed views from various pages in your app by sharing the MedicationDataSource. This centralizes your data and makes it more maintainable as your app grows.

Too many entries for NavigationStack
 
 
Q