简体   繁体   English

异步/等待:尝试访问填充了从 firebase 存储中下载的图像的数组时出现“超出范围错误”

[英]Async/Await: "out of range error" when trying to access array filled with downloaded images from firebase storage

I tried to download successfully uploaded images to storage with the code:我尝试使用以下代码将成功上传的图像下载到存储中:

  func retrieveAllPictures(helloid: String) async {
        //Referenzen zu den Datenbanken
        let db = Firestore.firestore()
        //Alle Foto Ids in einem Array speichern
        let result = try? await db.collection("events").document(helloid).getDocument()
        allPictureIDs = (result?.data()!["pictures"] as? [String])!
        var image = UIImage()
        
        
        for path in allPictureIDs {
            let storage = Storage.storage().reference()
            let fileRef = storage.child(path)
            
  
      try? await fileRef.getData(maxSize: 1 * 1024 * 1024) { data, error in
                if let error = error {
                    return
                } else {
                    image = UIImage(data: data!)!
                    self.retrievedEventImages.append(image)
                }
            }
    }
}

this is how I try to access the array at index 0:这就是我尝试访问索引 0 处的数组的方式:

struct finalEventView: View {
    @EnvironmentObject var viewModel: AppViewModel
    var id: String
    var body: some View {
        
        NavigationView {
            VStack{
               
                if (viewModel.retrievedEventImages[0] != nil){
                Image(uiImage: viewModel.retrievedEventImages[0]!)
                }
                /*
                ForEach(viewModel.EventImages, id: \.self){ image in
                    Image(uiImage: image)
                        .resizable()
                        .frame(width: 110, height: 110)
                }*/
                Button(action: {
                    Task {
                        try? await viewModel.retrieveAllPictures(helloid: self.id)
                    }
                }, label: {Text("print image arr")})
            }}
        .onAppear{
            Task {
                try? await viewModel.retrieveAllPictures(helloid: self.id)
            }
        }
    }
}

when trying to debug the code, I see that retrievedEventImages is filled with the UIImages still when trying to access the array at index 0 I get an out of range error maybe someone knows how to fix it, any help is appreciated尝试调试代码时,我看到检索到的事件图像仍然充满 UIImages 尝试访问索引 0 处的数组时出现超出范围的错误,也许有人知道如何修复它,感谢任何帮助

Never access an item of an array in a SwiftUI view rendering area by index .永远不要按索引访问 SwiftUI 视图渲染区域中的数组项

In most cases the view is rendered the first time while the array is empty which causes the out of range crash.在大多数情况下,第一次渲染视图时数组为空,这会导致超出范围崩溃。

This kind of checking for the existence of an item is unswifty anyway, just use first and Optional Binding无论如何,这种检查项目是否存在的方法并不迅速,只需使用first和 Optional Binding

if let firstImage = viewModel.retrievedEventImages.first {
   Image(uiImage: firstImage)
}

Edit: Apparently there is no async version of getData() .编辑:显然没有getData()async版本。 You can adopt async/await with a Continuation您可以通过Continuation采用async/await

do {
    let data : Data = try await withCheckedThrowingContinuation { continuation in
        fileRef.getData(maxSize: 1 * 1024 * 1024) { data, error in
            if let error = error {
                continuation.resume(throwing: error)
            } else {
                continuation.resume(returning: data!)
            }
        }
    }
    let image = UIImage(data: data)!
    self.retrievedEventImages.append(image)
} catch {
    print(error)
    // or better show a message to the user
}

See @vadian answer for an explanation of part of the issue.有关部分问题的解释,请参阅@vadian 答案。

To add an await/async code solution as well.还要添加等待/异步代码解决方案。 I'm doing this on macOS - the iOS solution is similar.我在 macOS 上执行此操作 - iOS 解决方案类似。

Task {
    let resultData = try! await imageRef.data(maxSize: 1 * 1024 * 1024)
    let image = NSImage(data: resultData) //UIImage for iOS
    self.retrievedEventImages.append(image)
}

Firebase used the await/async func data instead of getData to avoid naming collisions. Firebase 使用 await/async func data而不是getData以避免命名冲突。

There's probably more up-to-date info but see git 8289 for further reading.可能有更多最新信息,但请参阅git 8289以进一步阅读。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM