SwiftUI实现点击网格图片后滚动视图定位到对应图片
问题修复:点击网格图片后滚动视图定位到对应位置
问题根源
你的代码中,ScrollPostView内部重新初始化了PostGridViewModel并发起API请求获取帖子列表,这会导致两个关键问题:
- 重复请求API,造成资源浪费
- 视图出现时帖子数据尚未加载完成,
onAppear中设置的scrollPosition找不到对应ID,而数据加载完成后没有重新触发定位逻辑,最终导致滚动视图始终从第一张开始显示
解决方案
直接复用网格页面传递过来的postids数组,无需在ScrollPostView中重新加载数据,确保数据一致性并避免异步加载导致的定位失效。
修改后的ScrollPostView代码
struct ScrollPostView: View { let postids: [Post] let selectedpostid: Post.ID @State private var scrollPosition: Post.ID? let user: User init(user: User, postids: [Post], selectedpostid: Post.ID ) { self.user = user self.postids = postids self.selectedpostid = selectedpostid } var body: some View { ZStack{ Color(red: 0.1608, green: 0.4078, blue: 0.3725) .ignoresSafeArea() VStack(spacing: 2){ ScrollView{ VStack{ // 直接使用传入的postids数组,而非重新加载的viewModel.posts ForEach(postids) { post in posts_cell(post: post, user: user) } .padding(.horizontal) } .padding(.top, 20) .padding(.bottom,18) .scrollTargetLayout() } .scrollPosition(id: $scrollPosition, anchor: .center) .onAppear { // 视图出现时直接定位到选中的post ID scrollPosition = selectedpostid } .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) .padding(.top, 30) .padding(.bottom, 52) } } } }
可选:保留ViewModel的修改方案
如果你的业务逻辑需要在ScrollPostView中使用PostGridViewModel,可以修改ViewModel支持传入初始数据,并在数据更新时重新触发定位:
修改PostGridViewModel
class PostGridViewModel: ObservableObject{ private let user: User @Published var posts = [Post]() // 添加initialPosts参数,支持传入已有数据 init(user: User, initialPosts: [Post]? = nil) { self.user = user if let initialPosts = initialPosts { self.posts = initialPosts } else { Task { try await fetchUserPosts() } } } @MainActor func fetchUserPosts() async throws { self.posts = try await PostService.FetchUserPosts(uid: user.id) for i in 0 ..< posts.count { posts[i].user = self.user } } }
修改ScrollPostView的初始化和定位逻辑
struct ScrollPostView: View { @StateObject var viewModel: PostGridViewModel let postids: [Post] let selectedpostid: Post.ID @State private var scrollPosition: Post.ID? let user: User init(user: User, postids: [Post], selectedpostid: Post.ID ) { // 传入初始数据到ViewModel self._viewModel = StateObject(wrappedValue: PostGridViewModel(user: user, initialPosts: postids)) self.user = user self.postids = postids self.selectedpostid = selectedpostid } var body: some View { ZStack{ Color(red: 0.1608, green: 0.4078, blue: 0.3725) .ignoresSafeArea() VStack(spacing: 2){ ScrollView{ VStack{ ForEach(viewModel.posts) {post in posts_cell(post: post, user: user) } .padding(.horizontal) } .padding(.top, 20) .padding(.bottom,18) .scrollTargetLayout() } .scrollPosition(id: $scrollPosition, anchor: .center) .onAppear { scrollPosition = selectedpostid } // 监听posts变化,数据更新后重新定位 .onChange(of: viewModel.posts) { _ in scrollPosition = selectedpostid } .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) .padding(.top, 30) .padding(.bottom, 52) } } } }
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

