Since the UITableView is a UIScrollView subclass, you could implement the UIScrollViewDelegate method:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
withVelocity:(CGPoint)velocity
targetContentOffset:(inout CGPoint *)targetContentOffset
And then compute what the closest desired target content offset is that you want, and set that on the inout CGPoint parameter.
I've just tried this and it works well.
First, retrieve the unguided offset like this:
CGFloat unguidedOffsetY = targetContentOffset->y;
Then Figure out through some math, where you'd want it to be, noting the height of the table header. Here's a sample in my code dealing with custom cells representing US States:
CGFloat guidedOffsetY;
if (unguidedOffsetY > kFirstStateTableViewOffsetHeight) {
int remainder = lroundf(unguidedOffsetY) % lroundf(kStateTableCell_Height_Unrotated);
log4Debug(@"Remainder: %d", remainder);
if (remainder < (kStateTableCell_Height_Unrotated/2)) {
guidedOffsetY = unguidedOffsetY - remainder;
}
else {
guidedOffsetY = unguidedOffsetY - remainder + kStateTableCell_Height_Unrotated;
}
}
else {
guidedOffsetY = 0;
}
targetContentOffset->y = guidedOffsetY;
The last line above, actually writes the value back into the inout parameter, which tells the scroll view that this is the y-offset you'd like it to snap to.
Finally, if you're dealing with a fetched results controller, and you want to know what just got snapped to, you can do something like this (in my example, the property "states" is the FRC for US States). I use that information to set a button title:
NSUInteger selectedStateIndexPosition = floorf((guidedOffsetY + kFirstStateTableViewOffsetHeight) / kStateTableCell_Height_Unrotated);
log4Debug(@"selectedStateIndexPosition: %d", selectedStateIndexPosition);
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:selectedStateIndexPosition inSection:0];
CCState *selectedState = [self.states objectAtIndexPath:indexPath];
log4Debug(@"Selected State: %@", selectedState.name);
self.stateSelectionButton.titleLabel.text = selectedState.name;
OFF-TOPIC NOTE: As you probably guessed, the "log4Debug" statements are just logging. Incidentally, I'm using Lumberjack for that, but I prefer the command syntax from the old Log4Cocoa.