swift - Reusable cell or wrong asynchronous image download from JSON data in TableView -


i have application downloads json data api , sets in tableview cells. @ point scrolling up/down in random cell image may change several times before has right image in it. no problems text data whatsoever. @ first thought problem reusability of cell, need destroy data before set new image. added method of tableviewcell cellforrowat path destroy data before setting cell:

func destroycelldata() {      self.newsimageview.image = nil     self.newstitlelabel.text = nil     self.taglabel.text = nil } 

then actual method setting cell:

override func tableview(_ tableview: uitableview, cellforrowat indexpath: indexpath) -> uitableviewcell {      guard let cell = tableview.dequeuereusablecell(withidentifier: "newscell") as? newstableviewcell else {          print("no such cell")         exit(14)     }      cell.loadingimageindicator.startanimating()      let data = datamanager.getdata()      let datatoinsert = data[indexpath.row]     cell.destroycelldata()     cell.setdatatocell(with: datatoinsert)      return cell } 

and method setdatatocell :

func setdatatocell(newsobject: jsonnews) {          self.newstitlelabel.text = newsobject.title         self.taglabel.text = newsobject.tag          let url = newsobject.imageurl         self.newsimageview.loadimageusingcachewithurlstring(url, placeholder: uiimage(named: "viewplaceholder"), indicator: loadingimageindicator)  } 

and load asynchronously image inside cell:

let imagecache = nscache<nsstring, uiimage>()  extension uiimageview {  func loadimageusingcachewithurlstring(_ urlstring: string, placeholder: uiimage?, indicator: uiactivityindicatorview? = nil) {      self.image = nil      if let cachedimage = imagecache.object(forkey: nsstring(string: urlstring)) {          self.image = cachedimage         indicator?.stopanimating()         return      }      guard let encodedstring = urlstring.addingpercentencoding(withallowedcharacters: .urlqueryallowed) else {          print("error loading url")         return     }      if let url = url(string: encodedstring) {          urlsession.shared.datatask(with: url, completionhandler: { (data, response, error) in              if error != nil {                  print("error loading images url: \(string(describing: error))")                  operationmanager.ui {                      self.image = placeholder                     indicator?.stopanimating()                 }                  return             }                  if let data = data {                      if let downloadedimage = uiimage(data: data) {                              print(urlstring)                             imagecache.setobject(downloadedimage, forkey: nsstring(string: urlstring))                          operationmanager.ui {                              self.image = downloadedimage                             indicator?.stopanimating()                     }                 }             }         }).resume()     } } 

}

so have question - problem lie in method in download , set image or problem in reusability of cell? , if possible give me hint of more appropriate way set image cell. in advance

without having code, suspect problem both reusable cells , async image downloading. in that, when reload cell, kicks off data task download image, , if second task started download different image, nothing happens first.

for example, lets first image 100mb, , second image reusabel cell 1kb. 1kb downloads faster. here flow

  1. load cell image1
  2. start download of image1
  3. load cell image2
  4. start download of image2
  5. complete download of image2
  6. set cell image image2
  7. complete download of image1
  8. set cell image image1

since data task of downloading image1 completed after image2 had been set, cell update show image1 after displaying image2, , show wrong image.

to solve problem, need someway cancel first operation, or rather, not update image view if no longer displaying data. there many ways this. 1 solution creating property of image url on cell, , when download completes, confirm correct url, , if is, update image view.

func setdatatocell(newsobject: jsonnews) {     // other code     self.imageurl = newsobject.imageurl }  // loadimageusingcachewithurlstring if let downloadedimage = uiimage(data: data) {      print(urlstring)     imagecache.setobject(downloadedimage, forkey: nsstring(string: urlstring))      operationmanager.ui {         if url.absolutestring == self.imageurl {             self.image = downloadedimage             indicator?.stopanimating()         }      } } 

note: didn't test of code, , wrote straight brain. have errors.

with said, recommend using third party image caching system alamofireimage or 1 of other ones people have commented on.


Comments

Popular posts from this blog

ios - MKAnnotationView layer is not of expected type: MKLayer -

ZeroMQ on Windows, with Qt Creator -

unity3d - Unity SceneManager.LoadScene quits application -