SwiftUI: Navigation doesn't work properly in List with Sections

Viewed 189

I'm trying to build a List with a Section for each different case of a custom enum I declared. The list shows and works perfectly, with all the instances of the model grouped by case in their respective section, but whenever I try to navigate to the detail view, it just shows it for a second and then automatically sends me back to the list, as if I hit the back button. This is the code I used:

import SwiftUI

enum Enum: String, Identifiable, CaseIterable {
    var id: UUID { UUID() }
    case case1 = "Case 1"
    case case2 = "Case 2"
    case case3 = "Case 3"
}
    
struct ProvaView: View {
    
    func listaModelliPerCaso(caso: Enum) -> [Model] {
        let array = dm.models.filter { $0.caso == caso }
        return array
    }
    
    @ObservedObject var dm: DataManager
    
    var body: some View {
        NavigationView {
            List {
                ForEach(Enum.allCases) { caso in
                    Section(header: Text(caso.rawValue)) {
                        ForEach(listaModelliPerCaso(caso: caso)) { model in
                            NavigationLink(
                                destination: ProvaDetailView(dm: dm, modello: model)) {
                                Text(model.nome)
                            }
                        }
                    }
                }
            }
            .navigationBarTitle(Text("Models List"), displayMode: .inline)
        }
    }
}

That's how it looks like: simulator screenshot

If I use a class instead of an enum, create an instance for each single case and store them into an array, and recall it with the ForEach, the problem disappears. I'm just really confused about why it behaves differently (and in such a weird way) when it's an enum instead.

Thank you very much in advance for any help you could provide!

1 Answers

The problem is in regenerated id (ie. UUID()) for your enum, so any call to allCases create new sections and destroy/recreate complete List.

The solution is to use something persistent instead, like rawValue:

enum Enum: String, Identifiable, CaseIterable {
    var id: String { self.rawValue }               // << here !!
    case case1 = "Case 1"
    case case2 = "Case 2"
    case case3 = "Case 3"
}

Tested with replicated code on Xcode 12.1 / iOS 14.1

Related