Maintaining offset when reloading RowsAtIndexPaths

I try to reload one tableViewCell, but it scrolls to the top every time ... I do not add or remove cells, I just want to change the color of the selected cells.

This is what I do in cellForRowAtIndexPath:

SMPChoiceViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ChoiceCell" forIndexPath:indexPath]; SMPChoice *choice = self.choices[indexPath.row - 1]; cell.choiceTextLabel.text = choice.text; if ([self.selectedChoices indexOfObject:choice] != NSNotFound) { cell.choiceTextLabel.textColor = [UIColor purpleColor]; } else { cell.choiceTextLabel.textColor = [UIColor blackColor]; } 

And this is what I do in the didSelectRowAtIndexPath file

 if ([self.selectedChoices indexOfObject:choice] != NSNotFound) { [self.selectedChoices removeObject:choice]; } else { [self.selectedChoices addObject:choice]; } CGPoint offSet = [tableView contentOffset]; [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; [tableView setContentOffset:offSet animated:NO]; 

But it just jumps, any suggestion?

PS I followed this topic but did not solve my question Calling reloadRowsAtIndexPaths removes tableView contentOffset

+6
source share
3 answers

I know this is an old question, but I had the same problem and could not find the answer anywhere.

After reloadRowsAtIndexPaths:withRowAnimation: tableView determines its offset using the estimated heights specified in tableView:estimatedHeightForRowAtIndexPath: Therefore, if the value you return is not accurate, its implementation will lead to a change in the offset of the table view after a reboot. I did not implement tableView:estimatedHeightForRowAtIndexPath: and the problem was fixed.

+8
source

Since for some mysterious reason, the table view determines a new offset after reloading some cells using the estimated row height, you want to make sure that tableView:estimatedHeightForRowAtIndexPath returns the correct data for the cells that have already been processed. To do this, you can cache the apparent line heights in the dictionary, and then use this correct data (or your rating for cells that are not already loaded.)

 fileprivate var heightForIndexPath = [NSIndexPath: CGFloat]() fileprivate let averageRowHeight: CGFloat = 300 //your best estimate //UITableViewDelegate override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { heightForIndexPath[indexPath] = cell.frame.height } override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return heightForIndexPath[indexPath] ?? averageRowHeight } 

(HUGE thanks to eyewt for understanding that the line height estimate is used to determine the new offset.)

+11
source

OBJ-C version of Daniel's answer:

 //rowHeightForIndexPath is an NSMutableDictionary - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { [self.rowHeightForIndexPath setObject:@(cell.frame.size.height) forKey:indexPath]; } - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { NSNumber *cachedHeight = [self.rowHeightForIndexPath objectForKey:indexPath]; return cachedHeight ? cachedHeight.floatValue : UITableViewAutomaticDimension; } 
0
source

Source: https://habr.com/ru/post/978613/


All Articles