2

I'm using the code below to force a uitableview to "snap to row":

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    // if decelerating, let scrollViewDidEndDecelerating: handle it
    if (decelerate == NO) {
        [self centerTable];
    }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    [self centerTable];
}

- (void)centerTable {
    NSIndexPath *pathForCenterCell = [self.tableView indexPathForRowAtPoint:CGPointMake(CGRectGetMidX(self.tableView.bounds), CGRectGetMidY(self.tableView.bounds))];

    [self.tableView scrollToRowAtIndexPath:pathForCenterCell atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}

It works fine in iOS9, however in iOS8 the table view does not allow me to snap to the first or last rows. If I put a breakpoint in centerTableafter the index path calculation I get this for the table view:

iOS9:

<UITableView: 0x7fb9a6ed8600; frame = (0 0; 300 132); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x7fb9ae14cae0>; layer = <CALayer: 0x7fb9ad1b1540>; contentOffset: {0, 0}; contentSize: {300, 220}>

iOS8:

<UITableView: 0x7ff6e2d59800; frame = (0 0; 300 132); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x7ff6e8726130>; layer = <CALayer: 0x7ff6e214b450>; contentOffset: {0, 0}; contentSize: {300, 132.5}>

Note that everything is the same, except the contentSize. This results in the index Path to be n+1 in iOS8 compared to iOS9.

So, why is contentSize calculated differently by the system in iOS8??? And what is the workaround?

soleil
  • 12,133
  • 33
  • 112
  • 183

1 Answers1

1

While I don't why the contentSize is different, here's my workaround for the centering accurately issue:

- (void)centerTableViewAnimated:(BOOL)animated {
     NSIndexPath *centerCellIndexPath = [self.tableView indexPathForRowAtPoint:CGPointMake(CGRectGetMidX(self.tableView.bounds), CGRectGetMidY(self.tableView.bounds))];

     CGPoint contentOffset = CGPointMake(0, (centerCellIndexPath.row * self.tableView.rowHeight) - ((self.tableView.frame.size.height / 2) - (self.tableView.rowHeight / 2)));

     [self.tableView setContentOffset:contentOffset animated:animated];
}

So basically, instead of trying to use scrollToRowAtIndexPath, I just set the contentOffset directly (and you can animate it, which is nice). This seems to work just fine on iOS 8 and iOS 9.

Sam V.
  • 411
  • 4
  • 8