使用Async/Await从Firebase Storage取图片数组时触发越界错误
问题修复方案
1. 修正异步下载逻辑错误
你在retrieveAllPictures里混用了Firebase Storage的async/await版本和回调版本getData方法,导致下载任务执行顺序混乱——函数会在所有图片下载完成前就返回,视图会在数组为空时尝试访问索引0,直接引发崩溃。
修复后的retrieveAllPictures函数:
func retrieveAllPictures(helloid: String) async { let db = Firestore.firestore() // 用可选绑定替代强制解包,避免空值崩溃 guard let result = try? await db.collection("events").document(helloid).getDocument(), let pictureIDs = result.data()?["pictures"] as? [String] else { allPictureIDs = [] retrievedEventImages.removeAll() return } allPictureIDs = pictureIDs retrievedEventImages.removeAll() // 清空旧数据,避免重复加载 let storage = Storage.storage().reference() for path in pictureIDs { let fileRef = storage.child(path) // 使用纯async/await版本的getData,无需闭包 do { let data = try await fileRef.getData(maxSize: 1 * 1024 * 1024) if let image = UIImage(data: data) { retrievedEventImages.append(image) } } catch { print("图片下载失败: \(error.localizedDescription)") } } }
2. 修复视图数组访问逻辑
直接访问retrievedEventImages[0]会在数组为空时触发越界崩溃,必须先判断数组是否非空,同时移除不必要的强制解包:
修复后的finalEventView:
struct finalEventView: View { @EnvironmentObject var viewModel: AppViewModel var id: String var body: some View { NavigationView { VStack { // 先判断数组非空,再访问索引0 if !viewModel.retrievedEventImages.isEmpty { Image(uiImage: viewModel.retrievedEventImages[0]) .resizable() .scaledToFit() } else { // 数组为空时显示加载占位 Text("图片加载中...") } Button(action: { Task { await viewModel.retrieveAllPictures(helloid: id) } }, label: {Text("重新加载图片")}) } } .onAppear { Task { await viewModel.retrieveAllPictures(helloid: id) } } } }
3. 确保视图响应数组更新
如果retrievedEventImages是普通数组,视图不会自动刷新,需要在AppViewModel中将其声明为@Published属性(前提是AppViewModel遵循ObservableObject):
class AppViewModel: ObservableObject { @Published var retrievedEventImages: [UIImage] = [] // 其他属性... }
这样数组内容更新时,视图会自动刷新并显示加载完成的图片。
内容的提问来源于stack exchange,提问作者anni_m
相关产品推荐
相关产品推荐

