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
}
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?
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.
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.
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.
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
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With