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:
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
2
Answers
Never access an item of an array in a SwiftUI view rendering area by index.
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 BindingEdit: Apparently there is no
async
version ofgetData()
. You can adoptasync/await
with aContinuation
See @vadian answer for an explanation of part of the issue.
To add an await/async code solution as well. I’m doing this on macOS – the iOS solution is similar.
Firebase used the await/async func
data
instead ofgetData
to avoid naming collisions.There’s probably more up-to-date info but see git 8289 for further reading.