ios - Updating Height of Self-Sizing Table View Cell With Text View -
i have table view similar "compose" screen in mail, 1 of cells used text input. i'd cell resize automatically constraining contentview of cell uitextview subview using auto layout. table view's rowheight set uitableviewautomaticdimension, , estimatedrowheight set 44. additionally, text view's scrollenabled property set false reports intrinsiccontentsize.
however, find cell not update height lines of text entered user, though text view update intrinsic content size. far know, way request manually table view call beginupdates() , endupdates(). height of cell correctly updated, causes re-layout of entire table view. here's (someone else's) sample code demonstrating problem.
how can reflect changes in cell's text view without laying out entire table view?
throttled solution
the trouble reloadrowsatindexpaths uitextfield resignfirstresponder since cell, in essence, reloaded: i.e. destroyed.
conversely, beginupdates() & endupdates() maintain existing cells, yet jitters when invoked on cell containing scrollenabled uitextview if triggered every single textviewdidchange.
limit updates frequency
this solution based on popular textviewdidchange approach, reduces or stops flickering entirely postponing update.
subclass uitableviewcell:
class tableviewtextviewcell : uitableviewcell, uitextviewdelegate { var refreshcell:(() -> void)? = nil var textviewdirtycount = 0 // mark: - uitextviewdelegate func textviewdidchange(_ textview: uitextview) { textviewdirtycount += 1 perform(#selector(tableviewtextviewcell.queuedtextvewdidchange), with: nil, afterdelay: 0.3) // wait until typing stopped } func textviewdidbeginediting(_ textview: uitextview) { textviewdirtycount = 0 // initialize queuedtextvewdidchange } func textviewdidendediting(_ textview: uitextview) { textviewdirtycount = -1 // prevent further queuedtextvewdidchange } func queuedtextvewdidchange() { if textviewdirtycount > 0 { textviewdirtycount -= 1 if 0 == textviewdirtycount, let refreshcell = refreshcell { refreshcell() } } } } dequeue & update closure:
override func tableview(_ tableview: uitableview, cellforrowat indexpath: indexpath) -> uitableviewcell { let cell = tableview.dequeuereusablecellwithidentifier( "cell", forindexpath: indexpath) as! tableviewtextviewcell cell.refreshcell = { () -> void in tableview.beginupdates() tableview.endupdates() } return cell } notice 0.3 seconds delay after last character has been entered ; if less 0.3 seconds has elapsed since last change, no update takes place. reduces flickering.
► find solution on github , additional details on swift recipes.

Comments
Post a Comment