ios - Swift, dispatch_group_wait not waiting -


i trying use grand central dispatch wait files finish download before continuing. question spin-off one: swift (ios), waiting images finish downloading before returning.

i trying find out how dispatch_group_wait (or similar) wait , not continue before downloads have finished. note if use nsthread.sleepfortimeinterval instead of calling downloadimage, waits fine.

what missing?

class imagedownloader {      var updateresult = adupdateresult()      private let filemanager = nsfilemanager.defaultmanager()     private let imagedirectoryurl = nsurl(fileurlwithpath: settings.addirectory, isdirectory: true)      private let group = dispatch_group_create()     private let downloadqueue = dispatch_queue_create("com.acme.downloader", dispatch_queue_serial)      func downloadimages(imagefilesonserver: [adfileinfo]) {          dispatch_group_async(group, downloadqueue) {              serverfile in imagefilesonserver {                 print("start downloading \(serverfile.filename)")                 //nsthread.sleepfortimeinterval(3) // using sleep instead of calling downloadimage makes dispatch_group_wait below work                 self.downloadimage(serverfile)             }         }         dispatch_group_wait(group, dispatch_time_forever); // not wait downloads finish.  why?          print("all done!") // gets here early!     }      private func downloadimage(serverfile: adfileinfo) {          let destinationpath = imagedirectoryurl.urlbyappendingpathcomponent(serverfile.filename)          alamofire.download(.get, serverfile.imageurl) { temporaryurl, response in return destinationpath }         .response { _, _, _, error in             if let error = error {                 print("error downloading \(serverfile.filename): \(error)")             } else {                 self.updateresult.filesdownloaded++                 print("done downloading \(serverfile.filename)")             }         }     } }  

note: these downloads in response http post request , using http server (swifter) not support asynchronous operations, need wait full downloads complete before returning response (see original question referenced above more details).

when using dispatch_group_async call methods are, themselves, asynchronous, group finish of asynchronous tasks have started, not wait them finish. instead, can manually call dispatch_group_enter before make asynchronous call, , call dispatch_group_leave when asynchronous call finish. dispatch_group_wait behave expected.

to accomplish this, though, first change downloadimage include completion handler parameter:

private func downloadimage(serverfile: adfileinfo, completionhandler: (nserror?)->()) {     let destinationpath = imagedirectoryurl.urlbyappendingpathcomponent(serverfile.filename)      alamofire.download(.get, serverfile.imageurl) { temporaryurl, response in return destinationpath }         .response { _, _, _, error in             if let error = error {                 print("error downloading \(serverfile.filename): \(error)")             } else {                 print("done downloading \(serverfile.filename)")             }             completionhandler(error)     } } 

i've made completion handler passes error code. tweak see fit, illustrates idea.

but, having provided completion handler, now, when downloads, can create group, "enter" group before initiate each download, "leave" group when completion handler called asynchronously.

but dispatch_group_wait can deadlock if you're not careful, can block ui if done main thread, etc. better, can use dispatch_group_notify achieve desired behavior.

func downloadimages(imagefilesonserver: [adfileinfo], completionhandler: (int) -> ()) {     let group = dispatch_group_create()      var downloaded = 0      serverfile in imagefilesonserver {         dispatch_group_enter(group)         print("start downloading \(serverfile.filename)")         self.downloadimage(serverfile) { error in             if error == nil {                 downloaded += 1             }             dispatch_group_leave(group)         }     }     dispatch_group_notify(group, dispatch_get_main_queue()) {         completionhandler(downloaded)     } } 

and you'd call so:

downloadimages(arrayofadfileinfo) { downloaded in     // initiate whatever want when downloads done      print("all done! \(downloaded) downloaded successfully.") }  // don't contingent upon downloading of images here 

Comments