0

I have the following view:

My trouble is when a list item moves between upFrontAlters and otherAlters inside FrontViewModelHelper which just has the referenced properties as publishable. The row moves between the section, but the view changes that would go along with isOtherView don't toggle with it. It's stuck as which ever one it was in when the app started.

struct FrontViewInternal: View {
    @StateObject var state: FrontViewModelHelper
    let dispatch: (FrontActions) -> Void
    var body: some View {
        let textBinding: Binding<String> = Binding(
            get: { state.search },
            set: { search in dispatch(FrontActions.FilterAlters(search: search))}
        )
        NavigationView {
            LazyVStack(alignment: .leading, pinnedViews: [.sectionHeaders]) {
                Section(header: Text("Front Alters")) {
                    if (state.upFrontAlters.isEmpty) {
                        Text("No Up Front Alters!")
                    } else {
                        ForEach(state.upFrontAlters, id: \.id) { alter in
                            FrontOtherRowView(
                                id: alter.id,
                                avatarUrl: alter.avatarUrl,
                                hexColor: alter.colorHex,
                                name: alter.name,
                                pronouns: alter.pronouns,
                                dispatch: dispatch,
                                isOtherView: false
                            )
                        }
                    }
                }
                
                Divider()
                
                Section(header: Text("Other Alters")) {
                    ForEach(state.otherAlters, id: \.id) { alter in
                        FrontOtherRowView(
                            id: alter.id,
                            avatarUrl: alter.avatarUrl,
                            hexColor: alter.colorHex,
                            name: alter.name,
                            pronouns: alter.pronouns,
                            dispatch: dispatch,
                            isOtherView: true
                        )
                    }
                }
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .searchable(text: textBinding)
            .background(Color.background)
            .navigationTitle("Alters")
            .padding()
            .navigationBarItems(
                trailing: Button(
                    action: {},
                    label: {
                        Image(systemName: "plus.app")
                    }
                )
            )
        }
    }
} 
Ken White
  • 123,280
  • 14
  • 225
  • 444
Cate Daniel
  • 724
  • 2
  • 14
  • 30
  • 1
    So two of your elements can have the same `id`? [This can lead to undefined behavior](https://stackoverflow.com/questions/72811440/swiftui-foreach-explanation#:~:text=That%27s%20why%20a%20stable%20ID%20is%20needed%20that%27s%20unique%20among%20the%20set%20you%20want%20to%20present%3A%20you%20get%20unexpected%20results%20if%20the%20ID%20is%20not%20stable%20or%20is%20not%20unique). Take a look at [this article](https://www.hackingwithswift.com/quick-start/swiftui/how-to-create-views-in-a-loop-using-foreach) for more information. –  Mar 01 '23 at 03:38
  • Does this answer your question? [SwiftUI ForEach explanation](https://stackoverflow.com/questions/72811440/swiftui-foreach-explanation) –  Mar 01 '23 at 03:39
  • So it can only exist in the overall list once. It can be in the up front list, or the other list, not both. When it moves from one to the other, it doesn't re-draw the cell though, leaving me with the row not updating. – Cate Daniel Mar 01 '23 at 03:52
  • Give your lazyVStack id, Like - lazyVStack{}.id(id), id can be int, here let's take 0. I don't understand what action you perform that change action, but when you perform action just change id like "id += 1". Maybe this can help you update the view. – Namra Parmar Mar 01 '23 at 05:35
  • So the alter can either be upfront or not, so the boolean just configures which button is shown and which action the buttons do – Cate Daniel Mar 01 '23 at 13:25
  • adding `LazyVStack{}.id("front\(id)")` to the id comes up with `Cannot convert value of type 'some View' to expected argument type 'KeyPath.Element, ID>'` – Cate Daniel Mar 01 '23 at 13:35

1 Answers1

0

Ever realize there's a simpler answer staring in the face?

There's no reason I have to have one giant list, I can have two LazyVSTacks

Cate Daniel
  • 724
  • 2
  • 14
  • 30