Home > Software design >  Return Image from Function in Swift
Return Image from Function in Swift

Time:08-09

I have tried to return an Image or UIImage from the function below but there is an issue that says
"Unexpected non-void return value in void function."

I am retrieving the Image from Firebase Storage and just want to return it...

func retrivePhotos(path: String) -> UIImage {
    let storageRef = Storage.storage().reference()
    let fileRef = storageRef.child(path)
    // Retrieve the data with the path
    fileRef.getData(maxSize: 5 * 1024 * 1024) { data, error in
        if error == nil && data != nil {
            let image = UIImage(data: data!)
            return image
        }
    }
}

CodePudding user response:

The thing to understand is that your call to getData(maxSize:) is a separate asynchronous function. That function does not, and cannot, return the image in its return. It needs to start a network request. It starts that network request and then returns immediately. When the function returns, the network request hasn't even begun sending over the network yet.

The return in the braces following that function call are a return from a closure, which is a block of code that you are passing to the function.

Your function also cannot return an image if it is getting the image using an async function. (unless you rewrite it using async/await, a new language feature that is a little beyond the scope of this question, and likely beyond your current understanding.)

You need to rewrite your function to take a completion handler, just like the getData(maxSize:) function takes a completion handler:

typealias ImageHandler = (UIImage?) -> Void

func retrivePhotos(path: String, completion: ImageHandler)  {
    let storageRef = Storage.storage().reference()
    let fileRef = storageRef.child(path)
    // Retrieve the data with the path
    fileRef.getData(maxSize: 5 * 1024 * 1024) { data, error in
        if error == nil && data != nil {
            let image = UIImage(data: data!)
            completion(image)
        } else {
            completion(nil)
        }
    }
}

(That is over-simplified. You'd probably write it to take a Result instead of an Optional UIImage.)

Think of async functions like this. The main program is you, cooking dinner for your family. You realize you are out of milk, so you send your kid to the store to buy some. You don't hand your kid some money and expect them to hand you back the milk right then and there. You hand them the money, tell them to get you milk, and then go back to the rest of the cooking. At some time in the future, your kid comes back and either gives you the milk (The success case) or tells you there was a problem that prevented them from getting the milk (the error case.)

At the point your kid come back from the store, you run the "kid is back from the store" completion handler. You either go into sauce-making mode with the milk, or an error handler where you decide what to do since you don't have milk.

  • Related