4

High-level description:

There is a nested view problem when a state object is being passed through views. At the end of the deepest view in the hierarchy, the app is frozen and memory consumption is increasing continuously.

Use-case

Partners list → Partner detail → (Locations list) → Location detail

Code-snippets

class PartnerViewModel: ObservableObject {
    @Published var partners: [Partner] = Partner.partners
}

This view is loaded into a TabView and a NavigationStack components in the parent class.

struct PartnerListView: View {
    @StateObject var viewModel = PartnerViewModel()

    var body: some View {
        List($viewModel.partners, id: \.self) { $partner in
            NavigationLink {
                PartnerDetailView(partner: $partner)
            } label: {
                Text(partner.name)
            }
        }
    }
}
struct PartnerDetailView: View {
    @Binding var partner: Partner

    var body: some View {
        Form {
            Section("Locations") {
                List($partner.locations, id: \.self) { $location in
                    NavigationLink {
                        LocationDetailView(location: $location)
                    } label: {
                        Text(location.name)
                    }
                }
            }

        }
    }
}
struct LocationDetailView: View {
    @Binding var location: Location
    var body: some View {
        TextField("Name", text: $location.name)
    }
}

The following snippets are workaround and it works but it might be temporary because I don't understand why the first attempt doesn't work and why this one does. I haven't found any resources that could give an example of this scenario.

struct PartnerDetailView: View {
    @Binding var partner: Partner

    var body: some View {
        Form {
            Section("Locations") {
                List($partner.locations, id: \.self) { $location in
                    NavigationLink {
                        LocationDetailView(partner: $partner, locationIndex: partner.locations.firstIndex(of: location) ?? 0)
                    } label: {
                        Text(location.name)
                    }
                }
            }

        }
    }
}
struct LocationDetailView: View {
    @Binding var partner: Partner
    var locationIndex: Int
    
    var body: some View {
        TextField("Name", text: $partner.locations[locationIndex].name)
    }
}

Is it possible that I am not passing values between views properly?🤔

enter image description here

3
  • Using an index in a SwiftUI ForEach is a code smell. Which one is the workaround? Using the index or the first code block?
    – Paulw11
    Dec 25, 2022 at 1:33
  • @Paulw11 Using the index is the workaround and yes I know it is a code smell but it really concerns me.
    – vargab
    Dec 25, 2022 at 8:56
  • Do you have a lot of fields to edit in LocationDetailView, if not maybe skip the navigation link and edit them directly in the list in PartnerDetailView. Dec 25, 2022 at 11:32

0

Your Answer

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