Post not yet marked as solved
Post marked as unsolved with 2 replies, 3,870 views
I am working with a ScrollView and a LazyVStack that can have many rows, sometimes 500 or more. My rows are expandable on tap. Performance of expand/collapse is unacceptable when the number of rows exceeds 100. The more rows, the more performance degrades.
This is the gist of my code:
struct PlaceView: View {
		/* ... */
		var place: Place
		@Binding expandedPlaceId: Int
		var content: some View {
				VStack(alignment: .leading) {
						Text(place.name)
						
						if self.expandedPlaceId.wrappedValue == place.id {
								VStack(alignment: .leading) {
										Text(place.city)
								}
						}
				}
		}
}
struct PlacesListView: View {
		/*...*/
		@State expandedPlaceId = -1
		var body: some View {
			ScrollView {
				LazyVStack {
					ForEach(places, id: \.id) { place in
						PlaceView(place: place, expandedPlaceId: self.$expandedPlaceId)
								.onTapGesture { self.selectDeselect(place) }
								.animation(.linear(duration: 0.3))
					}
			 }
		 }
	}
}
I created an init function in PlaceView with the following:
print("calling int for place \(place.id)")
What I have noticed is when expanding, every single PlaceView calls init. For 20 or 30 PlaceView rows this is not a problem, but with several hundred views this creates a choppiness in animation and delays the expansion of the detail section.
Is there any workaround for this problem? It does not matter if I use LazyVStack or VStack (which itself is unexpected).
Here is an example project that can easily be modified to highlight the problem: https://github.com/V8tr/ExpandableListSwiftUI
In the above project, simply add the following to PlaceView.swift
init(place: Place, isExpanded: Bool) {
self.place = place
self.isExpanded = isExpanded
print("PlaceView init \(self.place.id)")
}