ios - Getting duplicate cells with UITableViewController cellForRowAtIndexPath -


i trying create table view using uitableviewcontroller.

the 'cellforrowatindexpath' doesn't seem working right-- have pre-loaded photos , comments parse , put them in array, , want pictures fill screen width, doing manual calculations on them resize.

i doing unusual things table view right, data duplicated.

i know there here i'm not getting, i'm not sure is... maybe need else bind data, or "prepareforreuse" method?

i have included code uitableviewcontroller subclass , uitablecell subclass wrote.

import uikit  class youtableviewcell: uitableviewcell {  var recipeid:string = "" var recipename:string = "" var imageheight:cgfloat = 0 var labelheight:cgfloat = 0  // need this? override func prepareforreuse() {     self.textlabel!.text = recipeid //put label name     self.imageview!.image = nil  }  override func setselected(selected: bool, animated: bool) {     super.setselected(selected, animated: animated)      // configure view selected state  }   }   class youtableviewcontroller: basetableviewcontroller { // uitableviewcontroller {  var labelcreated = [bool]() var imagecreated = [bool]()  var cellarray = [int:youtableviewcell]()   override func viewdidload() {     super.viewdidload()      self.tableview.delegate = self     self.tableview.datasource = self      self.view.addgesturerecognizer(self.revealviewcontroller().pangesturerecognizer())      if !isyoudataloaded {         _ = datacontroller.getyoupagedata()     }       // initialize height arrays     _ in 0..<youfeed.count {         labelcreated.append(false)         imagecreated.append(false)     }       // uncomment following line preserve selection between presentations     // self.clearsselectiononviewwillappear = false      // uncomment following line display edit button in navigation bar view controller.     // self.navigationitem.rightbarbuttonitem = self.editbuttonitem()     self.navigationcontroller?.settoolbarhidden(false, animated: false) }   // ... skipping down   override func tableview(tableview: uitableview, numberofrowsinsection section: int) -> int {     // return feedarray.count     return youfeed.count }    override func tableview(tableview: uitableview, cellforrowatindexpath indexpath: nsindexpath) -> uitableviewcell {      print("cellforrowatindexpath : \(indexpath.row)")      // reference cell     cellarray[indexpath.row] = (tableview.dequeuereusablecellwithidentifier("cell", forindexpath: indexpath) as! youtableviewcell)     let thiscell:youtableviewcell = cellarray[indexpath.row]!       // temp -- border     thiscell.layer.borderwidth = 2.0     thiscell.layer.bordercolor = uicolor.blackcolor().cgcolor      let meal = youfeed[indexpath.row].recipe      // if image exists     if let foodimage:uiimage = meal.imageview.image! uiimage {         var namelabel:uilabel = uilabel()         var fitimageview:uiimageview?         if imagecreated[indexpath.row] == false {             print("for image #\(indexpath.row)")             fitimageview = layouthelper.fitimageincell(foodimage, cell: thiscell, name: meal.recipename)             thiscell.contentview.addsubview(fitimageview!)              thiscell.imageheight = fitimageview!.frame.height             fitimageview!.frame.origin.y = 0             print("img height : \(fitimageview!.image!.size.height)")             imagecreated[indexpath.row] = true         }         if labelcreated[indexpath.row] == false {             // create label             var captionstring = ""             if let mealnametext:string = meal.recipename string {                 captionstring += mealnametext             }              if let posttext:string = meal.desc string {                 captionstring += "\n" + posttext             } else {                 print("meal desc null")             }             if let numforks:int = meal.forks int {                 captionstring += "\n" + string(numforks) + " forks"             }             if (fitimageview != nil) {                 namelabel = layouthelper.fitlabelbelowimageview(captionstring, imageview: fitimageview!, cell: thiscell, yoffset: 0)                 thiscell.addsubview(namelabel)                 thiscell.labelheight = namelabel.frame.height             }         }     }      return thiscell }  override func tableview(tableview: uitableview, heightforrowatindexpath indexpath: nsindexpath) -> cgfloat {     let thiscell = cellarray[indexpath.row]      var thisht:cgfloat = 0     if thiscell != nil {         thisht = thiscell!.labelheight + thiscell!.imageheight     }     return thisht } } 

when re-use cells (which thing do!) must re-initialize entire cell every time cellforrowatindexpath called. because possible when make call:

tableview.dequeuereusablecellwithidentifier 

it returning cell have initialized. example, let's have 4 rows visible on screen:

row 1 - cell [image 1] row 2 - cell b [image 2] row 3 - cell c [image 3] row 4 - cell d [image 4] 

now, let's scroll down , row 1 no longer on screen, row 5 has appeared. possible cell receive row 5 same exact cell @ row 1. so, after call tableview.dequeuereusablecellwithidentifier row 5 looks this:

row 2 - cell b [image 2] row 3 - cell c [image 3] row 4 - cell d [image 4] row 5 - cell [image 1] <-- 

you need update cell point image 5. may work fine in code , this:

row 2 - cell b [image 2] row 3 - cell c [image 3] row 4 - cell d [image 4] row 5 - cell [image 5] <-- 

now, let's scroll , row 1 assigned cell again:

row 1 - cell [image 5] <-- row 2 - cell b [image 2] row 3 - cell c [image 3] row 4 - cell d [image 4] 

since storing arrays keep track of rows have been initialized (imagecreated, labelcreated) cell won't updated point image 1:

// true, not execute if imagecreated[indexpath.row] == false 

this means rid of imagecreated , labelcreated arrays , perform code initialize cells every time cellforrowatindexpath called.

also, recommend getting rid of cellarray , not storing references cells (for same reasons mentioned above). can cache cell heights , should fine because not tied re-usable cells. this:

var cellheightarray = [int:cgfloat]() 

since doing calculations in cellforrowatindexpath set height @ bottom:

cellheightarray[indexpath.row] = thiscell!.labelheight + thiscell!.imageheight; 

then set array in heightforrowatindexpath:

override func tableview(tableview: uitableview, heightforrowatindexpath indexpath: nsindexpath) -> cgfloat {     let thiscellheight = cellheightarray[indexpath.row]      var thisht:cgfloat = 0     if thiscellheight != nil {         thisht = thiscellheight     }     return thisht } 

by default, believe heightforrowatindexpath called before cellforrowatindexpath. in case of cells have height of 0 until reload tableview. @ post more information:

why heightforrowatindexpath: come before cellforrowatindexpath:?


Comments

Popular posts from this blog

Ansible - ERROR! the field 'hosts' is required but was not set -

customize file_field button ruby on rails -

SoapUI on windows 10 - high DPI/4K scaling issue -