2

I need to create an application that have the same behavior as built-in Reminder App. There are some problems to create this:

  • Cells that have dynamic height and "grow" as the content of the UITextView
  • Select the touched cell
  • Refresh the height of the cell when the user has edited the content(on the fly)

I've already solved the dynamic height, using some trick.

The problem that remains is:

How to know which cell the user has selected if the cell is "fully" with the UITextView ?

Right Now i've used the method textViewDidBeginEditing to know the cell and scroll the UITableView to it:

- (void)textViewDidBeginEditing:(UITextView*)textView
{
    MemoViewCell* cell = (MemoViewCell *)[self parentCellFor:textView];
    if (cell)
    {
        NSIndexPath* indexPath = [self.tableView indexPathForCell:cell];
        currentIndexPath = indexPath;
        [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
    }
}

- (UITableViewCell*)parentCellFor:(UIView*)view
{
    if (!view)
        return nil;
    if ([view isMemberOfClass:[MemoViewCell class]])
        return (UITableViewCell*)view;
    return [self parentCellFor:view.superview];
}

How to refresh the cell height without lost the focus?

To this, i've used this method:

-(void)textViewDidChange:(UITextView *)textView
{
    NSMutableDictionary *dataSourceItem = [self.model.dataSource objectAtIndex:currentIndexPath.row];
    [dataSourceItem setObject:textView.text forKeyedSubscript:@"body"];
    [self.model.dataSource setObject:dataSourceItem atIndexedSubscript:currentIndexPath.row];

    [self.tableView beginUpdates];
    [self.tableView endUpdates];
}

When the text change, i get the new text, i change it in the Model and i call beginUpdated and endUpdates.

Sure, this works, but all is extremly slow... do you have some idea to to this in a more elegant way and maybe... efficient?

If i call reloadRowsAtIndexPaths: i lost the focus on the cell.

Mistre83
  • 2,677
  • 6
  • 40
  • 77
  • what is slow? Only change the height of the cell when the length of the string exceeds the the current number of lines. Only change when a new line is added. – rakeshbs Jan 02 '15 at 15:32
  • If i run the code i've posted and i select a cell and continuing press delete, the CPU go at 100% usage (iOS Simulator). Right now i'm testing it with many rows (80) and beginUpdate + endUpdate cause the reload for all the rows. If i use [tableView reloadRowsAdIndexPaths] sure this is faster, but i lost the focus on the current cell. – Mistre83 Jan 02 '15 at 15:40
  • how are you calculating the height of the rows? Do you have to keep calling begin update and end update every text change? Isn't it only necessary when finishing editing and the text goes beyond one line? – rakeshbs Jan 02 '15 at 15:44
  • To calculate the UITextViewHeight i use this:http://stackoverflow.com/a/19493268/1537060 and with constraints i get the cell right setup. As reminder app, i should resize the cell when the text become bigger and need more space. – Mistre83 Jan 02 '15 at 15:47

1 Answers1

2

First of all, if you use the delegate method - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath; in your dynamic height trick, remember to implement this method along - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath;, it helps a lot in terms of performance.

Then to focus on your specific project, if I correctly understood your goal, what you really want is to update the layout of your table view only when your text view is modified. Currently you're updating it at each text change. You might consider using a condition inside -(void)textViewDidChange:(UITextView *)textView, such as :

if ([textView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height !=
textView.frame.size.height) {
    [self.tableView beginUpdates];
    [self.tableView endUpdates];
}

The condition given as example will work only if your existing cell layout respects the intrinsic content size of the text view, otherwise you will need to adapt the condition.

TripleH
  • 142
  • 1
  • 5
  • what i could say.. Thanks!!! introducing estimatedHeightForRowAtIndexPath (returing 44.0) have solved all the problems. With this, the system (re)load only few cells and not all the cell in the table view and now all is very fast!!! – Mistre83 Jan 02 '15 at 15:58