SwiftUI中LazyVGrid底部ProgressView的onAppear未触发问题
LazyVGrid中ProgressView的onAppear未触发原因分析
问题描述
我使用LazyVGrid展示电影海报,尝试通过异步函数实现下拉加载更多内容。在ForEach末尾放置了ProgressView,通过它的onAppear事件触发加载操作,但有时该事件并未触发(关联的print语句也无输出)。
问题演示:
相关代码:
LazyVGrid(columns: [GridItem(.adaptive(minimum: 150))], spacing: 15) { ForEach(filmObserver.movies, id: \.id) { movie in NavigationLink(destination: ItemDetailView(type: itemType.Film, itemId: movie.id)){ ItemCardView(movieData: movie) } } if filmObserver.hasNext && !filmObserver.movies.isEmpty { ProgressView() .frame(width: 150, height: 200, alignment: .center) .onAppear { print("refresh!!!") filmObserver.fetchItem(type: itemType.Film) } } }
可能的原因
- LazyVGrid预加载范围限制:LazyVGrid只会预加载可视区域附近的内容,如果ProgressView被现有列表项推到了预加载范围之外,SwiftUI不会提前渲染它,也就不会触发
onAppear。比如现有内容刚好填满或超出屏幕,滚动时还没到ProgressView的位置就已经加载完新数据,导致它永远没机会进入预加载区域。 - 条件判断的时序冲突:
filmObserver.hasNext和!filmObserver.movies.isEmpty的状态可能在滚动过程中快速变化。比如最后一页数据加载完成后,hasNext被设为false,ProgressView会被立即移除,就算它即将进入可视区域,也会因条件不满足被销毁,onAppear无法触发。另外如果加载新数据的速度过快,ProgressView刚要渲染就被新的列表项替换,也会导致事件丢失。 - 视图层级更新干扰:当
filmObserver.movies更新导致LazyVGrid布局突变时,SwiftUI可能会重新计算视图树,忽略ProgressView的onAppear事件。比如一次加载大量电影项,直接将ProgressView挤出了可视和预加载范围。 - 视图未被添加到视图树:如果初始加载的内容就占满屏幕,且
hasNext初始为false,后续hasNext变为true但未触发视图更新,ProgressView根本没被添加到视图树中,自然不会触发onAppear。
内容的提问来源于stack exchange,提问作者Bam Bou
相关产品推荐
相关产品推荐

