I've been stuck with this problem for some time now, and I ran out of useful google results.
I've got two requests, the first one retrieves some links from a server and in the other request I download the images from the links. After all the images finished downloading, I return the result to a view controller.
Int the code requestBanners()
is called from a UIViewController, entering the dispatch group. In theory, before leaving the dispatch group storeImage()
should be called for every url that I got from the server, and on every call it should enter and leave the dispatch group, adding the image to an array. Once finished downloading all the images, it leaves the dispatch group, and fires the notify()
to execute setUpCollection()
on the UIViewController.
Using print()
as guidance to see what's really happening, I get:
I'm downloading the urls
Now I'm in the UIViewController (this
print()
is called in the implementation ofsetUpCollection()
)
I'm downloading an image
When it actually should be downloading the urls, then downloading the images and only then, returning to the UIViewController
I've used semaphores at first, but then I thought using a dispatch group would be a cleaner solution.
On both approaches, the empty bannersArr is returned before finishing downloading the images. Maybe that compact map is messing everything up.
Here's the code:
class BannersHelper {
private var bannersArr: [UIImage] = []
private let dispatchGroup = DispatchGroup()
private var delegate: LoadBanners? = nil
init(delegate: LoadBanners) {
self.delegate = delegate
dispatchGroup.notify(queue: .main) {
self.delegate?.setUpCollection(errImg: self.bannersArr)
}
}
func requestBanners() {
print("I'm downloading the urls\n")
self.dispatchGroup.enter()
ServiceParametria.getBanners(handler: { response in
guard let bannersResponse = response as? BannerModel else {
return
}
let banners = bannersResponse.data as! [DataBannerModel]
let _ = banners.compactMap({self.storeImage(model: $0)})
self.dispatchGroup.leave()
})
}
private func storeImage(model: DataBannerModel) {
print("I'm downloading an image\n")
self.dispatchGroup.enter()
ServiceParametria.getImage(url: model.urlImagen!, handler: { result in
let image = result as! UIImage
self.bannersArr.append(image)
self.dispatchGroup.leave()
})
}
}
Is there a better way to do this or am I just using the dispatch group wrong?