ios - NSURLSession in For Loop to Download Image Data then add to NSMutableArray -


my application has uitableview cell contains uicollectionview subview (not reused). collectionview's cells have single uiimageview hold picture. trying download of images @ once, store them in array, , display contents of array in collectionview cell once images downloaded. in objc have done many times using nsurlconnection trying use swift , nsurlconnection achieve i'm running believe may either concurrency or semantics issues. maybe 1 of guys point me in right direction because feel i'm spending time on this.

in uitableview's cell subclass contains collectionview calling

func downloadphotoswithurls(urls: [string]) {      var imagesmutablearray = nsmutablearray()      url in urls {          nsurlsession.sharedsession().datataskwithurl(nsurl(string: url)!, completionhandler: { (data, repsonse, err) -> void in              if let imgdata = data {                  if let image = uiimage(data: imgdata) {                      imagesmutablearray.addobject(image)                  }                  else {                      // put in "photo unavailable" pic                 }             }              else {                  // put in "photo unavailable" pic             }          }).resume()      }      // update (but async op not done)     if let downloadedimages: [uiimage] = imagesmutablearray nsarray as? [uiimage] {          self.images = downloadedimages          dispatch_async(dispatch_get_main_queue(), { () -> void in              self.collectionview.reloaddata()         })      }  } 

problem time call collectionview reloaded, images have not been fetched. asynchronous operations in loop blame. how call // update code after images downloaded?

if want wait series of asynchronous tasks finish, create dispatch_group_t, enter group before starting each request, leave group in completion block, , can rely on dispatch_group_notify called when each "enter" matched "leave"

func downloadphotoswithurls(urls: [string]) {     var images = [uiimage]()      let group = dispatch_group_create()      url in urls {         dispatch_group_enter(group)         nsurlsession.sharedsession().datataskwithurl(nsurl(string: url)!, completionhandler: { data, response, error in              if let imgdata = data {                 if let image = uiimage(data: imgdata) {                     dispatch_sync(dispatch_get_main_queue()) {                         images.append(image)                     }                 } else {                     // put in "photo unavailable" pic                 }             } else {                 // put in "photo unavailable" pic             }              dispatch_group_leave(group)         }).resume()     }      // update     dispatch_group_notify(group, dispatch_get_main_queue()) {         self.images = images         self.collectionview.reloaddata()     } } 

note, should synchronize updates of array of images (mutable arrays not thread safe).

--

having answered question, must confess advise 2 further, yet significant changes:

  1. you shouldn't hold images in array (because if there many, can run out of memory). jpeg or png files might not large, when images uncompressed in ram, can take lot of memory , can memory warnings.

    you might consider downloading images persistent storage, not memory. if want hold images in memory, use nscache performance reasons (but purge upon memory warning).

    if don't have many images, or they're small may not critical. if you're looking scalable solution, don't require app hold of images in array.

  2. you might not want wait of images before reloading collection view. people advise lazy loading. if have 1000 images , 20 visible @ time, why wait 1000 images? focus on loading images visible cells. also, might want see images pop collection view they're downloaded (so rather waiting first 20 visible images downloaded, show them come in).

    you accomplish having cellforitematindexpath initiate image download asynchronously , update cell when it's done.


Comments

Popular posts from this blog

java - UnknownEntityTypeException: Unable to locate persister (Hibernate 5.0) -

python - ValueError: empty vocabulary; perhaps the documents only contain stop words -

ubuntu - collect2: fatal error: ld terminated with signal 9 [Killed] -