I have an imageLoader function, that loads the images while the other code keeps running. Now I want that same function to run first, before all the other code keeps running.
This is the function:
//calling the function
ImageLoader.sharedLoader.imageForUrl(urlstring as String, completionHandler:{(image: UIImage?, url: String) in
self.productImageView.image = image!
})
//the function itself
func imageForUrl(urlString: String, completionHandler:(image: UIImage?, url: String) -> ()) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {()in
var data: NSData? = self.cache.objectForKey(urlString) as? NSData
if let goodData = data {
let image = UIImage(data: goodData)
dispatch_async(dispatch_get_main_queue(), {() in
completionHandler(image: image, url: urlString)
})
return
}
var downloadTask: NSURLSessionDataTask = NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: urlString)!, completionHandler: {(data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
if (error != nil) {
completionHandler(image: nil, url: urlString)
return
}
if data != nil {
let image = UIImage(data: data)
self.cache.setObject(data, forKey: urlString)
dispatch_async(dispatch_get_main_queue(), {() in
completionHandler(image: image, url: urlString)
})
return
}
})
downloadTask.resume()
})
}
how do I turn this int a normal function that does the same, but in sync
I just quickly made a function that takes an async function with a handler as a parameter and return the result synchronous, but be aware: Asynchronous methods from API's are like this for a reason, it may take a long time and therefore should be run on a background queue not to block the main queue. Anyways here is the function with an example:
Basically you create a
dispatch_group
and enter it, provide a handler in which you leave thisdispatch_group
and just wait until the group is left. Swift generics work very nicely with this.More detail on how it works:
A dispatch group is created, which can be entered or left, we can also wait until a dispatch group is empty by calling
dispatch_group_wait
.In my function, The result type is
R
which is also the type that the handler accepts. I'm declaring a function as my handler which is just like any other handler for an async function, but instead of doing something with the result, it just stores it in the optionalresult
and then gives the signal that the group is left, which will resume our wait command.So we enter the group, tell the async function to do its thing with the handler, and just wait until it's finished, whereas we know it's finished when the handler is called and the group therefore left.