I have a problem when trying to scroll to top a ScrollView. I use a ScrollViewReader inside a SCrollView and I subscribe with .onReceive() my lazyVStack to a property @PUlished scrollToTop from my view model. I see that it receives the notification properly but my Scroll doesn't move to top. Here is my code:
struct NewsList: View {
@ObservedObject var viewModel: NewsListViewModel
@State var isDetailsViewShown = false
var body: some View {
NavigationView {
GeometryReader { geometry in
VStack {
if !viewModel.isSearching {
TitleView(title: "News")
.frame(height: geometry.size.height / 11)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0)
.padding(.horizontal, 13)
.padding(.bottom, 0)
}
SearchView(searchText: $viewModel.searchText, isSearching: $viewModel.isSearching)
.padding([.trailing, .leading, .bottom], 13)
if !viewModel.isSearching {
TabsView(selected: $viewModel.selectedTab)
.padding(.horizontal, 13)
}
ScrollView {
ScrollViewReader { reader in
LazyVStack(spacing: 15) {
ForEach(articles.indices, id: \.self) { index in
NavigationLink(destination: DetailsNewsView(article: articles[index])) {
NewsCell(article: articles[index])
.onAppear {
checkActionForLastCell(index: index)
}
}.buttonStyle(FlatLinkStyle())
}
}.animation(nil)
.padding(.horizontal, 8)
.onReceive(viewModel.$scrollTop) { (scrollToTop) in
guard let first = articles.first, scrollToTop else { return}
reader.scrollTo(first, anchor: .top)
print(scrollToTop)
}
}
}
}
.background(Color.background.edgesIgnoringSafeArea(.all))
.navigationBarHidden(true)
.onAppear {
//viewModel.getNews()
}
}
}
}
var articles: [Article] {
guard viewModel.searchedArticles.isEmpty || viewModel.searchText.count < 3 else { return viewModel.searchedArticles}
return viewModel.tabsArticles[viewModel.selectedTab] ?? []
}
func checkActionForLastCell(index: Int) {
if index == articles.count - 1 {
viewModel.getNextPageNews(isPaging: true)
}
}
}
and inside my ViewModel I just use a timer to see if it receives the notification
class NewsListViewModel: ObservableObject {
/..../
@Published var scrollTop = false
init() {
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
self.scrollTop = true
}
}
}
I get printed the notification and the reader.scrollTo(first, anchor: .top) get executed... but my table is not scrolled to top.