Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return value from completion handler - Swift

Tags:

ios

swift

I'm using a loadImage method in a Utilities class and am having some trouble with returning images via closures. Basically because my code could return either an image or an error, assigning it to an image property when the method is called will not work.

Is the approach I'm using wrong in the method declaration of the class, or should I be calling the method differently to anticipate potentially differing results? Thanks

public class UtilitiesService: NSObject {
    public class func loadImage(urlString:String)
    {

    var imgURL: NSURL = NSURL(string: urlString)!
    let request: NSURLRequest = NSURLRequest(URL: imgURL)
    NSURLConnection.sendAsynchronousRequest(
        request, queue: NSOperationQueue.mainQueue(),
        completionHandler: {(response: NSURLResponse!,data: NSData!,error: NSError!) -> Void in
            if error == nil {
                self.returnImage(data)
            }
    })
}

public class func returnImage(imageData: NSData) -> UIImage {

    return UIImage(data: imageData)!

}
}

//// view controller
class someView: UIViewController {
var image.image = loadImage(url) ///will throw a return type error
 }
like image 891
Phil Hudson Avatar asked Jul 24 '15 10:07

Phil Hudson


People also ask

Can closure return value Swift?

Closures can also return values, and they are written similarly to parameters: you write them inside your closure, directly before the in keyword. SPONSORED Why are Swift reference types bad for app startup time, and what's the performance cost of protocol conformances?

How do completion handlers work Swift?

A completion handler in Swift is a function that calls back when a task completes. This is why it is also called a callback function. A callback function is passed as an argument into another function. When this function completes running a task, it executes the callback function.

How do I pass a completion handler in Swift?

So, when you need to escape the execution of the closure use the @escaping attribute in Swift 3. The above-shown error of the compiler will disappear after making closure as escaping by using the @escaping attribute.

What is completion closure?

Closures are self-contained blocks of functionality that can be passed around and used in your code. Said differently, a closure is a block of code that you can assign to a variable. You can then pass it around in your code, for instance to another function.


1 Answers

Add a handler to your loadImage func:

Swift 3

 func loadImage(_ urlString: String, handler:@escaping (_ image:UIImage?)-> Void)
    {

        let imageURL: URL = URL(string: urlString)!

        URLSession.shared.dataTask(with: imageURL) { (data, _, _) in
            if let data = data{
                handler(UIImage(data: data))
            }
        }.resume()
    }

Call func like this:

loadImage("SomeURL") { (image) -> Void in
            if let image = image{
                DispatchQueue.main.async {
                    self.imageView.image = image
                }
            }
        }

Swift 2.3

func loadImage(urlString: String, handler: (image:UIImage?)-> Void)
    {

        let imageURL: NSURL = NSURL(string: urlString)!

        NSURLSession.sharedSession().dataTaskWithURL(imageURL) { (data, _, _) in
            if let data = data{
                handler(image: UIImage(data: data))
            }
            }.resume()
    }

Call func like this:

  loadImage("someURL") { (image) -> Void in
            if let image = image{
                dispatch_async(dispatch_get_main_queue()) {
                    self.imageView.image = image
                }
            }
        }
like image 107
Hamza Ansari Avatar answered Sep 29 '22 05:09

Hamza Ansari