0

My function ends before all data can be retrieved from the fire storage and returns empty. How can I get the data before returning?

Code:

func listItem() -> [imageitem]{
        let storage = Storage.storage()
        let storageRef = storage.reference().child("images/image")
        var array = [imageitem]()
        
        storageRef.listAll { (result, error) in
            if let error = error {
                print("error")
                print(error)
            }
            print("storagereference")
                result?.items.forEach({ StorageReference in
                    print(StorageReference)
                    print(StorageReference.name)

                    
                    StorageReference.getData(maxSize: 5*1024*1024) {data, error in
                        if error == nil && data != nil{
                            if let image = UIImage(data: data!){
                                    let element =  imageitem(title: StorageReference.name, image: Image(uiImage: image))
                                    array.append(element)
                                    print(array)
                            }
                        }
                    }
                })
            
            print("end",array)
        }
        return array
    }

Console:

storagereference
gs://proj-69776.appspot.com/images/image/gorilla.jpg
gorilla.jpg
gs://proj-69776.appspot.com/images/image/test.jpg
test.jpg
end []
[proj.ListView.imageitem(title: "test.jpg", image: SwiftUI.Image(provider: SwiftUI.ImageProviderBox<__C.UIImage>))]
[proj.ListView.imageitem(title: "test.jpg", image: SwiftUI.Image(provider: SwiftUI.ImageProviderBox<__C.UIImage>)), proj.ListView.imageitem(title: "gorilla.jpg", image: SwiftUI.Image(provider: SwiftUI.ImageProviderBox<__C.UIImage>))]

adding an await before the addData gives me an error
Cannot pass function of type '(StorageReference) async -> Void' to parameter expecting synchronous function type

  • Be careful when you mix closures with concurrency (async await) you need a "Continuation" Check out Meet async/await in Swift from #wwdc21 https://developer.apple.com/wwdc21/10132 – lorem ipsum Dec 16 '22 at 17:32

1 Answers1

0

You cannot return data that is loaded asynchronously with a return statement like that, because the return runs well before you ever append any element to the array. If you set breakpoints and run the code in a debugger you can most easily validate that.

Instead, you'll want to pass in a closure/callback or use a dispatch queue to get the value out of your function into the calling context.

For examples of how to do this, see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • 2
    Easier is to use the `async` variations of the APIs. See https://github.com/firebase/firebase-ios-sdk/blob/master/FirebaseStorage/Sources/AsyncAwait.swift#L31 – Paul Beusterien Dec 16 '22 at 20:17