I have a list that contains a refresh button that would refresh the content of that row when a user taps on that. My implementation works, but the list view will get reset and scrolled back to the top of the list.
I have reviewed the SO post here for a solution, but it seems that my implementation does not have any .id(UUID().uuidString)
to begin with.
Code:
struct FavouritesListView: View {
@StateObject private var viewModel = FavouritesListViewModel()
var body: some View {
List {
ForEach(viewModel.favouriteBusStops) { busStop in
Section {
FavouriteView(busStop: busStop)
}
}
}
}
}
struct FavouriteView: View {
@StateObject private var viewModel: BusStopDetailViewModel
var busStop: BusStopEntity
init(busStop: BusStopEntity) {
self.busStop = busStop
_viewModel = StateObject(wrappedValue: BusStopDetailViewModel(busStop: busStop))
}
var body: some View {
VStack(alignment: .leading) {
HStack(spacing: 20) {
//Other UI components
//Refresh button
Button {
viewModel.refresh(busStop: busStop)
} label: {
Image(systemName: "arrow.clockwise")
}
}
if viewModel.isLoading {
CenteredCircularProgressView()
} else {
if let arrivalInfo = viewModel.arrivalInfo {
//Other UI components
}
}
}
}
}
class BusStopDetailViewModel: ObservableObject {
@Published var arrivalInfo: BusArrivalInfo?
@Published var isLoading = false
init(busStop: BusStopEntity) {
getArrivalInfo(busStop: busStop)
}
func getArrivalInfo(busStop: BusStopEntity) {
isLoading = true
APIClient.shared.getBusArrivalInfo(busStopCode: busStop.busStopCode) { result in
DispatchQueue.main.async {
switch result {
case .success(let arrivalInfo):
self.arrivalInfo = arrivalInfo
case .failure(let error):
print("Err", error.localizedDescription)
}
self.isLoading = false
}
}
}
func refresh(busStop: BusStopEntity) {
getArrivalInfo(busStop: busStop)
}
}
What I'm looking for is that only that row refreshes when the refresh button is tapped, and that the scrollView does not get reset to the top.