Phil Hudson Phil Hudson - 2 months ago 37
iOS Question

Return value from completion handler - 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
}

Answer

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
                }
            }
        }
Comments