I have to design an Explore page with SwiftUI and this view has a spotlight slider with some other objects that each row includes some items, so I have a VStack to scroll the Explore objects and each object has an HStack to scroll the items for that object.
I also have to implement pagination for the page, so I am forced to use LazyVStack to add a Color.clear object at the end of the Stack to request the next page from the server.
so the problem is in scrolling the view I have a lag and it's not scrolling smoothly.
ZStack {
ScrollView(.vertical, showsIndicators: true) {
VStack {
if let spotLightItem = viewModel.exploreSections.filter({ $0.type == .spotlight}).first {
ExploreSpotlightComponentView(sectionData: spotLightItem)
.frame(height: 576)
.environmentObject(viewModel)
LazyVStack {
ForEach(viewModel.exploreSections.sorted(by: { $0.priority ?? 0 < $1.priority ?? 0}), id: \.title) { item in
switch item.type {
case .categoryHorizontalLarge:
CategoryHorizontalLargeSectionView(sectionData: item)
.environmentObject(viewModel)
case .categoryHorizontalMedium:
CategoryHorizontalMediumSectionView(sectionData: item)
.padding(.bottom)
case .categoryHorizontalSmall:
CategoryHorizontalSmallSectionView(sectionData: item)
.padding(.bottom)
case .categories:
CategoriesComponentView(sectionData: item)
.padding(.bottom)
case .map:
ExploreMapComponentView(sectionData: item, showMapView: true)
.environmentObject(exploreMapViewModel)
case .campaign:
CampaignSliderSectionView(sectionData: item)
.frame(height: 150)
.padding(.bottom)
default:
EmptyView()
}
}//: FOREACH ITEMS
if viewModel.currentPageNumber < viewModel.metaDataLastpageNumber {
// LazyVStack (alignment: .center, spacing: 0) {
Color.clear
.frame(width: 20, height: 20)
.onAppear {
viewModel.fetchData(nextPage: true, showLoader: false)
}
Spacer()
.frame(height: 20)
// }
}
}//: LAZYVSTACK ITEMS
} //: VSTACK EXPLORE ITEMS
.ignoresSafeArea()
.padding(.bottom, 50)
}
}//: SCROLLVIEW
.ignoresSafeArea()
.background(
Color(uiColor: .baseBackground)
.ignoresSafeArea()
)
.onAppear {
if !viewModel.didFinishSetup {
viewModel.didFinishSetup.toggle()
viewModel.setupVM()
}
}
}//: ZSTACK
.navigationTitle("")
.navigationBarHidden(true)
}
I read something that it might be solved with List and I have to replace LazyVStack with List, so changed the code with the following code, but I faced two new problems with List, not only the List items don't fill entire the mobile screen, but also when I change the city, List items don't be updated while the variable that I am using is a @Published variable.
VStack {
List(viewModel.exploreSections) { exploreSection in
switch exploreSection.type {
case .spotlight:
ExploreSpotlightComponentView(sectionData: exploreSection)
.frame(height: 576)
.environmentObject(viewModel)
.frame(maxWidth: .infinity)
case .categoryHorizontalLarge:
CategoryHorizontalLargeSectionView(sectionData: exploreSection)
.environmentObject(viewModel)
.frame(height: 280)
.frame(maxWidth: .infinity)
case .categoryHorizontalMedium:
CategoryHorizontalMediumSectionView(sectionData: exploreSection)
.frame(height: 176)
case .categoryHorizontalSmall:
CategoryHorizontalSmallSectionView(sectionData: exploreSection)
.frame(height: 150)
case .categories:
CategoriesComponentView(sectionData: exploreSection)
.frame(height: 298)
case .map:
ExploreMapComponentView(sectionData: exploreSection, showMapView: true)
.environmentObject(exploreMapViewModel)
.frame(height: 302)
.frame(maxWidth: .infinity)
.ignoresSafeArea()
case .campaign:
CampaignSliderSectionView(sectionData: exploreSection)
.frame(height: 150)
.padding(.bottom)
}
}
.frame(maxWidth: .infinity)
.ignoresSafeArea()
.listRowInsets(.init(top: 0, leading: 0, bottom: 0, trailing: 0))
.background(
Color(uiColor: .baseBackground)
)
.id(viewModel.exploreSections.compactMap({ $0.id }))
.listStyle(GroupedListStyle())
}
.onAppear {
if !viewModel.didFinishSetup {
viewModel.didFinishSetup.toggle()
viewModel.setupVM()
}
}
.ignoresSafeArea()