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