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
- load cell
image1
- start download of
image1
- load cell
image2
- start download of
image2
- complete download of
image2
- set cell image
image2
- complete download of
image1
- 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
Post a Comment