ios - UITableView Cells shifting positions or disappearing entirely on scroll -
i developing , application iphone in swift, , have run peculiar error: in 1 of uitableviewcontrollers,enter code here cells disappear or change sections when scroll , down on table view.
i've been dealing issue few days now, , has prompted me recode entire class, no avail. have researched extensively on error, , believe has data source , how tableview handles it, , have noticed other users have had same problem before, cannot find solution applies problems.
for example, here seems deal cell height, have continued check , double check code, , cell height returns correct values.
in addition, this post talks different errors tableview's data source, have strong pointer datasource's alert array , content , heights correct in cellforrowatindexpath.
this post deals question, doing tableview on main thread.
currently tableview has 4 sections: first, second, , fourth contain 1 cell , third has dynamic amount of cells based on amount of alerts user has added (for example, has 3 alert cells plus 1 "add alert" cell @ bottom). cells affected in 2, 3, , 4 sections.
this tableview should always:
but, however, here happens when scroll:
i first create variables here:
var currentprayer: prayer! // prayer user editing var prayeralerts: nsmutableorderedset! // mutable set of prayer alerts included in prayer
then initialize them in viewdidload:
override func viewdidload() { super.viewdidload() if currentprayer == nil { nsexception(name: "prayerexception", reason: "current prayer nil! unable show prayer details!", userinfo: nil).raise() } navitem.title = currentprayer.name // sets nav bar title current prayer name prayeralerts = currentprayer.alerts.mutablecopy() as! nsmutableorderedset // passes currentprayer alerts copy called prayeralerts prayeralertscount = prayeralerts.count + 1 }
below tableview methods:
here cellforrowatindexpath:
override func tableview(tableview: uitableview, cellforrowatindexpath indexpath: nsindexpath) -> uitableviewcell { println("cellforrowatindexpath called \(cellforrowrefreshcount) time") cellforrowrefreshcount += 1 switch indexpath.section { case 0: var cell = tableview.dequeuereusablecellwithidentifier(detailsextendedcellid, forindexpath: indexpath) as! prayerdetailsextendedcell cell.currentprayer = currentprayer cell.refreshcell() return cell case 1: var cell = tableview.dequeuereusablecellwithidentifier(setprayerdatecellid, forindexpath: indexpath) as! addprayerdatecell cell.currentprayer = currentprayer cell.refreshcell(false, selectedprayer: cell.currentprayer) return cell case 2: if indexpath.row == prayeralerts.count { var cell = tableview.dequeuereusablecellwithidentifier(addnewalertcellid, forindexpath: indexpath) as! addprayeralertcell cell.currentprayer = currentprayer cell.refreshcell(false, selectedprayer: currentprayer) cell.savebutton.addtarget(self, action: "didsavenewalert", forcontrolevents: .touchdown) return cell } else { var cell = tableview.dequeuereusablecellwithidentifier(prayeralertcellid, forindexpath: indexpath) as! prayeralertcell let currentalert = prayeralerts[indexpath.row] as! alert cell.alertlabel.text = alertstore.sharedinstance.convertdatetostring(currentalert.alertdate) return cell } case 3: var cell = tableview.dequeuereusablecellwithidentifier(answeredprayercellid, forindexpath: indexpath) as! prayeransweredcell cell.accessorytype = currentprayer.answered == true ? .checkmark : .none return cell default: return uitableviewcell() } }
and numberofrowsinsection:
override func tableview(tableview: uitableview, numberofrowsinsection section: int) -> int { switch section { case 0: println("returning 1 row section 0"); return 1 case 1: println("returning 1 row section 1"); return 1 case 2: println("returning \(prayeralertscount) rows section 2"); return prayeralertscount case 3: println("returning 1 row section 3"); return 1 default: println("returning 0 rows section default"); return 0 } }
and heightforrowatindexpath:
override func tableview(tableview: uitableview, heightforrowatindexpath indexpath: nsindexpath) -> cgfloat { switch indexpath.section { case 0: return uitableviewautomaticdimension case 1: let cell = tableview.cellforrowatindexpath(indexpath) as? addprayerdatecell if let thiscell = cell { let isadding = thiscell.isaddingdate if isadding { if thiscell.selectedtype == prayertype.none || thiscell.selectedtype == prayertype.daily { println("selected type none or daily") println("returning height of 89 addprayerdatecell") return 89 } else { println("returning height of 309 addprayerdatecell") return 309 } } else { println("returning height of 44 addprayerdatecell") return 44 } } else { println("returning default height of 44 addprayerdatecell") return 44 } case 2: if indexpath.row == prayeralerts.count { let cell = tableview.cellforrowatindexpath(indexpath) as? addprayeralertcell if let thiscell = cell { let isadding = thiscell.isaddingalert if isadding { return 309 }; return 44 } else { return 44 } } else { return 44 } case 3: return 44 default: return 44 } }
and estimatedheightforrowatindexpath:
override func tableview(tableview: uitableview, estimatedheightforrowatindexpath indexpath: nsindexpath) -> cgfloat { switch indexpath.section { case 0: return 130 case 1: return 44 case 2: return 44 case 3: return 44 default: return 44 } }
i have tried editing these methods extensively, checking code in each individual cell. nothing seems work.
does have solutions error? can update more code if necessary, believe either data source problem, or cell's resuse creating error, cannot seem pinpoint anything. in advance help!
update
here addalertcell "refreshcell()" method uitableviewcell extension:
func refreshcell(didselect: bool, selectedprayer: prayer!) { tableview?.beginupdates() selectionstyle = didselect == true ? .none : .default savebutton.hidden = !didselect cancelbutton.hidden = !didselect addnewalertlabel.hidden = didselect isaddingalert = didselect datelabel.text = alertstore.sharedinstance.convertdatetostring(datepicker.date) println("addprayeralertcell: cell refreshed") tableview?.scrollenabled = !didselect tableview?.endupdates() }
uitableviewcell extension:
extension uitableviewcell { var tableview: uitableview? { { var table: uiview? = superview while !(table uitableview) && table != nil { table = table?.superview } return table as? uitableview } }
}
you shouldn't need call beginupdates
/ endupdates
when refresh cell - these methods used if adding / deleting rows or sections tableview.
what happens if remove beginupdates()
, endupdates()
calls?
Comments
Post a Comment