English 中文(简体)
Up view @
原标题:Updating state for an element of a @Published array, doesn t refresh the view

我有以下可观的班子,我曾试图把它当作一个可观察到的物体,以及一种障碍和其他各种企图。 该物体由<代码>Locationservice类别保存,该类别也是。 ObservableObject and it s being published in an [Location Toggleable]. 我的理解是,对该阵列的一个单独部分进行更新,并不一定公布该元素的更新,因为阵列本身实际上没有更新,只是阵列的一个要素的财产。 在变更财产时,我如何适当更新在<条码>@Published上的清单?

Failed Attempts

class LocationToggleable: Hashable, Identifiable {
    // Omitted unrelated properties
    var selected: Bool = false
}

class LocationToggleable: ObservableObject, Hashable, Identifiable {
    // Omitted unrelated properties
    @Published var selected: Bool = false
}

struct LocationToggleable: Hashable, Identifiable {
    // Omitted unrelated properties
    var selected: Bool = false
}

Location Service

class LocationService: ObservableObject {
    //Omitted unrelated properties/functions
    @Published var toggleableLocations: [LocationToggleable]
}

class LocationService: ObservableObject {
    //Omitted unrelated properties/functions
    @StateObject var toggleableLocations: [LocationToggleable]
}

class LocationService: ObservableObject {
    //Omitted unrelated properties/functions
    @ObservedObject var toggleableLocations: [LocationToggleable]
}

List

  • Partial Code, the else is just a copy of the true return
ForEach(locationService.toggleableLocations, id: .self) { item in
                            if item.selected {
                                Section(content: {}, header: {
                                    TrailDetailCardView(location: item.location)
                                        .frame(maxWidth: .infinity)
                                        .matchedGeometryEffect(id: "location-id-(item.id)", in: namespace)
                                        .onTapGesture {
                                            withAnimation {
                                                proxy.scrollTo(item.id, anchor: UnitPoint(x: 0, y: 0.01))
                                                locationService.setSelected(for: item, to: !item.selected)
                                            }
                                        }
                                })
                                .id(item.id)
                            }

Set Selected Function

  • This works right now, but that s only because I m forcing a publish update for the toggleableLocations and it reeks of a code-smell.
    func setSelected(for toggleableLocation: LocationToggleable, to selected: Bool) {
        if let currentIndex = toggleableLocations.firstIndex(where: { $0.selected }) {
            toggleableLocations[currentIndex].selected = false
        }
        toggleableLocation.selected = selected
        toggleableLocations = toggleableLocations
    }

Notes

  • SwiftUI updating array state doesn t update view This solution doesn t work in my case, because I need the object to maintain it s selected state for proper management of it s layout in the LazyVGrid. I also need the object to be Hashable for uses elsewhere in the code.
问题回答

You could try this approach as shown in the example code, to ...properly update a list, when a property is changed, on a @Published array.

The example code uses one @StateObject var locationService = LocationService(), the source of data truth. It also uses the $ sign in the ForEach to allow changes to be made to the item, and a simple item.selected.toggle() to toggle the selection.

struct LocationToggleable: Hashable, Identifiable {
    let id = UUID()  // <--- here
    // Omitted unrelated properties
    var selected: Bool
    var location: String  // <--- for testing
}

class LocationService: ObservableObject {
    //Omitted unrelated properties/functions
    @Published var toggleableLocations: [LocationToggleable] = [
        LocationToggleable(selected: true, location: "location-1"),
        LocationToggleable(selected: false, location: "location-2"),
        LocationToggleable(selected: true, location: "location-3")]  // <--- here for testing, else []
}

struct ContentView: View {
    @StateObject var locationService = LocationService() // <--- here
    
    var body: some View {
        ForEach($locationService.toggleableLocations) { $item in  // <--- here $
            if item.selected {
                Section(content: {}, header: {
                    TrailDetailCardView(location: item)  // <--- here
                        .frame(maxWidth: .infinity)
                       // .matchedGeometryEffect(id: "location-id-(item.id)", in: namespace)
                        .onTapGesture {
                            withAnimation {
//                                proxy.scrollTo(item.id, anchor: UnitPoint(x: 0, y: 0.01))
                                item.selected.toggle()  // <--- here
                            }
                        }
                })
                .id(item.id)
            } 
            // --- for testing
            else {
                Text("(item.location) not selected").id(item.id)
                    .onTapGesture {item.selected.toggle() }
            }
            
        }
    }
}


// for testing
struct TrailDetailCardView: View {
    var location: LocationToggleable // <--- here, use @Binding if required
    
    var body: some View {
        Text(location.selected ? "true" : "false").border(.red)
    }
}




相关问题
WordPress Data Storage Efficiency

I ve been asked to review a WordPress plugin of sorts and try to find ways of making it faster. The premise of this plugin is basically to store a bunch of users and shifts and appointments and ...

Convert a 2D array index into a 1D index

I have two arrays for a chess variant I am coding in java...I have a console version so far which represents the board as a 1D array (size is 32) but I am working on making a GUI for it and I want it ...

Convert an array of integers for use in a SQL "IN" clause

Surely there is a framework method that given an array of integers, strings etc converts them into a list that can be used in a SQL "IN" clause? e.g. int[] values = {1,2,3}; would go to "(1,2,3)"

Sorting twodimensional Array in AS3

So, i have a two-dimensional Array of ID s and vote count - voteArray[i][0] = ID, voteArray[i][1] = vote count I want the top 3 voted items to be displayed in different colors, so i have a 2nd Array -...

C++ Array Sort Me

Stuck on an array sorter. Have to sort numbers from largest to smallest. I m trying two loops (one nested in the other). Here s the code: int counter=0; // inner counter int counter2=0; // outer ...

PHP array callback functions for cleaning output

I have an array of output from a database. I am wondering what the cleanest way to filter the values is example array Array ( [0] => Array ( [title] => title 1 ...

Best practice of big javascript objects

sry for this imprecise topic name. I am querying a dataset a lot of times so using ajax request would end up in tons of http requests. For this reason I decided to use the json encode method to ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

热门标签