分页网格选中图片在预览页无法正常显示及崩溃问题求助
问题分析与解决方案
崩溃直接原因
- ViewModel数据不共享:预览页新建了独立的
GalleryViewModel实例,和列表页的ViewModel完全隔离——列表页已经加载了第二页图片,但预览页的ViewModel初始为空,调用getPhotosAlbumDetails时用resetPage: false,此时预览页ViewModel的page默认是1,第一次请求只会加载第一页50张图片,而你选中的索引是53,超出了预览页当前加载的图片数量。 - 数组越界访问:预览页的
photosArray参数默认是空数组,列表页导航时没有传入已加载的图片数组,当代码执行到photosArray[selectedImageIndex]时,直接触发数组越界崩溃。
解决方案
方案一:共享ViewModel(推荐)
让预览页复用列表页的ViewModel,直接使用已加载好的图片数据,无需重复请求:
- 修改预览页参数:
struct GalleryPrevIewView: View { @State var selectedImageIndex: Int @ObservedObject var viewModel: GalleryViewModel // 改为接收外部ViewModel var selectedDataID: String = "" // 移除原有的 @StateObject private var viewModel = GalleryViewModel() var body: some View { ZStack { Color.black TabView(selection: $selectedImageIndex) { ForEach(0..<viewModel.photos.count, id: \.self) { index in ZStack(alignment: .topLeading) { URLImageView(url: viewModel.photos[index].photoPath ?? "N/A" , placeholder: "PhotogalleryPlaceholder") .clipped() .scaledToFit() .tag(index) .frame(width: screenWidth) } } } .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)) } .onAppear { // 检查选中索引是否超出已加载数量,自动加载后续分页直到覆盖该索引 while selectedImageIndex >= viewModel.photos.count && viewModel.photos.count < (viewModel.photoDetails?.totalPhotos ?? 0) { viewModel.getPhotosAlbumDetails(ID: selectedDataID, resetPage: false) { _ in } } } } }
- 列表页导航时传递ViewModel:
Button { selectedImageIndex = ind NavigationManager.shared.navigateToRoute( .galleryPreview( selectedImageIndex: selectedImageIndex ?? 0, selectedID: self.selectedDataID, viewModel: viewModel // 传递当前ViewModel,需同步修改路由定义 ) ) } label: { // 原有按钮内容 }
方案二:传递已加载图片数组
如果无法共享ViewModel,就把列表页已加载的图片数组传递给预览页:
- 列表页导航传参:
Button { selectedImageIndex = ind NavigationManager.shared.navigateToRoute( .galleryPreview( selectedImageIndex: selectedImageIndex ?? 0, selectedID: self.selectedDataID, photosArray: viewModel.photos // 传入已加载的图片数组 ) ) } label: { // 原有按钮内容 }
- 修改预览页逻辑:
struct GalleryPrevIewView: View { @State var selectedImageIndex: Int var photosArray: [Photo] // 移除默认空数组,确保必须传入 @StateObject private var viewModel = GalleryViewModel() @State var selectedDataID: String = "" var body: some View { ZStack { Color.black TabView(selection: $selectedImageIndex) { ForEach(0..<viewModel.photos.count, id: \.self) { index in // 原有图片内容 } } .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)) } .onAppear { // 同步已加载的图片数组 viewModel.photos = photosArray // 根据每页50张计算当前页码 viewModel.page = (photosArray.count / 50) + 1 // 检查是否需要加载更多分页覆盖选中索引 if selectedImageIndex >= viewModel.photos.count && viewModel.photos.count < (viewModel.photoDetails?.totalPhotos ?? 0) { viewModel.getPhotosAlbumDetails(ID: selectedDataID, resetPage: false) { status in if status { // 处理极端情况:选中索引超出总图片数,设置为最后一张 selectedImageIndex = min(selectedImageIndex, viewModel.photos.count - 1) } } } } } }
紧急修复:避免数组越界
如果暂时无法调整ViewModel或传参逻辑,先给预览页的越界访问加判断:
else if selectedImageIndex < photosArray.count, let matchIndex = viewModel.photos.firstIndex(where: { $0.phID == photosArray[selectedImageIndex].phID }) { selectedImageIndex = matchIndex } else { // 索引无效时自动修正为最后一张有效图片 selectedImageIndex = max(0, viewModel.photos.count - 1) }
内容的提问来源于stack exchange,提问作者Swift
相关产品推荐
相关产品推荐

