Detect the current top cell in a UITableView after scrolling

You could try using UITableView's -indexPathsForVisibleRows or -indexPathForRowAtPoint.

For example, let's say that you want to print the indexPath of the topmost visible cell, when you stop dragging your table. You could do something like this:

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
    NSIndexPath *firstVisibleIndexPath = [[self.tableView indexPathsForVisibleRows] objectAtIndex:0];
    NSLog(@"first visible cell's section: %i, row: %i", firstVisibleIndexPath.section, firstVisibleIndexPath.row);
}

For Swift 3.0

let topVisibleIndexPath:IndexPath = self.tableView.indexPathsForVisibleRows![0]

This is the Swift 3+ code:

override func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
    let firstVisibleIndexPath = self.tableView.indexPathsForVisibleRows?[0]
    print("First visible cell section=\(firstVisibleIndexPath?.section), and row=\(firstVisibleIndexPath?.row)")
}

You get the index paths for the visible rows

NSArray* indexPaths = [tableView indexPathsForVisibleRows];

Then sort using compare:

NSArray* sortedIndexPaths = [indexPaths sortedArrayUsingSelector:@selector(compare:)];

Then get the first element's row

NSInteger row = [(NSIndexPath*)[sortedIndexPaths objectAtIndex:0] row];