Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITableView flickers/stutters while entering text in auto resizing TextView

Currently I have a UITableView with a resizing UITextView in it. The cell is resizing automatically using beginUpdates/endUpdates, but when it does it the table view stutters (See the gif below).

The end result is a UITableViewCell that has a textview in it that resizes based on it's content. Here is the code within the custom UITableViewCell class that causes the UITableView to update itself.

- (void)textViewDidChange:(UITextView *)textView {
    // This is a category on UITableViewCell to get the [self superView] as the UITableView
    UITableView *tableView = [self tableView];
    if (tableView){
        [tableView beginUpdates];
        [tableView endUpdates];
    }
}

Here are the things that I have already tried:

Get the current contentOffset and resetting it after the endUpdates but didn't work Disabling scrolling on the UITableView before updates and then enabling afterwards I tried returning NO always from - (BOOL)textViewShouldEndEditing:(UITextView *)textView My UITableView cell height is using UITableViewAutomaticDimension. Any other ideas or thoughts are welcome.

Here is a sample of what it looks like:

Table View Stutter

I am not looking to use any libraries so please no suggestions for that.

Thanks

Edit: Solution

Found Here: I do not want animation in the begin updates, end updates block for uitableview?

Credit to @JeffBowen for a great find (although hacky it is workable and allows me to still implement the UITableViewDelegate methods for supporting iOS 7). Turn animations off prior to performing update and then enable after update to prevent the UITableView from stuttering.

[UIView setAnimationsEnabled:NO];
[tableView beginUpdates];
[tableView endUpdates];
[UIView setAnimationsEnabled:YES];

If you don't need to use the Delegate methods and want a less hacky solution for iOS 8+ only then go with @Massmaker's answer below.

like image 510
DMCApps Avatar asked Dec 13 '14 15:12

DMCApps


2 Answers

Just disable animation before calling beginUpdates and re-enable it after calling endUpdates.

[UIView setAnimationsEnabled:NO];
[tableView beginUpdates];
[tableView endUpdates];
[UIView setAnimationsEnabled:YES];

Definitely a hack but works for now. Credit to my friend Beau who pointed me to this.

like image 140
Jeff Bowen Avatar answered Oct 15 '22 19:10

Jeff Bowen


My solution (for iOS 8) was first set in my viewController viewDidLoad

self.tableView.rowHeight = UITableViewAutomaticDimension;
// this line is needed to cell`s textview change cause resize the tableview`s cell
self.tableView.estimatedRowHeight = 50.0;

then, combining this article solution in Swift and some dirty thoughts I`ve set in my cell a property, called

@property (nonatomic, strong) UITableView *hostTableView;

and in cell-s -(void) textViewDidChange:(UITextView *)textView

 CGFloat currentTextViewHeight = _textContainer.bounds.size.height;
CGFloat toConstant = ceilf([_textContainer sizeThatFits:CGSizeMake(_textContainer.frame.size.width, FLT_MAX)].height);
if (toConstant  >  currentTextViewHeight)
{
    [_hostTableView beginUpdates];
    [_hostTableView endUpdates];
}

then in viewController

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

textCell.hostTableView = self.tableView;

after height change

like image 26
Massmaker Avatar answered Oct 15 '22 19:10

Massmaker