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.

frame delay

↻ replay animation


► find solution on github , additional details on swift recipes.


Comments

Popular posts from this blog

javascript - jQuery: Add class depending on URL in the best way -

caching - How to check if a url path exists in the service worker cache -

Redirect to a HTTPS version using .htaccess -