I am executing 20 data tasks with different URLs and filling an array with the results, but at the end of the function I still don't get the final array despite using the same queue.
class func getImages(photos:[Photo]){
var images:[UIImage?] = []
let arrayQueue = DispatchQueue(label: "imagesQueue",attributes: .concurrent)
for i in 0...20{
let url = EndPoints.getImage(farm: photos[i].farm, server: photos[i].server, id: photos[i].id, secret: photos[i].secret).url
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
arrayQueue.async(flags: .barrier) {
let image = UIImage(data: data!)!
images.append(image)
}
}
task.resume()
}
arrayQueue.sync {
print(images.count)
}
}
This function is supposed to print 21
, however it prints zero.
Of course it does because the end of the function is not the end in terms of the timeline. The print
line at the end of the method is executed immediately before any result of the data task has been added to the queue.
You need DispatchGroup
, the notify
closure is executed after all tasks are completed.
class func getImages(photos:[Photo]) {
var images:[UIImage] = [] // Why optional?
let group = DispatchGroup()
let arrayQueue = DispatchQueue(label: "imagesQueue", attributes: .concurrent)
for i in 0...20{
let url = EndPoints.getImage(farm: photos[i].farm, server: photos[i].server, id: photos[i].id, secret: photos[i].secret).url
group.enter()
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
arrayQueue.async(flags: .barrier) {
let image = UIImage(data: data!)!
images.append(image)
group.leave()
}
}
task.resume()
}
group.notify(queue: arrayQueue) {
print(images.count)
}
}
Be aware that your code crashes reliably when an error occurs...
And your custom queue is actually redundant and you are executing 21 tasks