47

a simple question but I don't seem to have the right terminology to search Stackoverflow by it.

I have a UITableView with no sections, the user can scroll up and down a long list of data (rows) presented inside this tableview.

Question: how can I detect the most top cell row number after the user scrolled. (for example, if the user is scrolling 30 cells down, the top cell after the scroll is = 30)

vikingosegundo
  • 52,040
  • 14
  • 137
  • 178
chewy
  • 8,207
  • 6
  • 42
  • 70

4 Answers4

77

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]
Patel Jigar
  • 2,141
  • 1
  • 23
  • 30
phi
  • 10,634
  • 6
  • 53
  • 88
  • 5
    I would sort the array as there's nothing (as far as I can see) in the documentation that says the index paths are sorted in ascending order. – jbat100 Nov 24 '11 at 15:52
  • 1
    It's a different question, but check `tableView scrollToRowAtIndexPath` – phi Nov 24 '11 at 16:06
  • 4
    Beware, `[self.tableView indexPathsForVisibleRows]` could be empty when the user scrolls a table view with bouncing enabled like a chick on speed. So be sure to check whether the method returned at least 1 index path. – Thomas Kekeisen Apr 14 '14 at 16:19
  • "indexPathsForVisibleRows" returns invisible rows as well. Any better approach? – Dipak Mar 01 '22 at 07:45
32

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];
jbat100
  • 16,757
  • 4
  • 45
  • 70
8

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)")
}
mathema
  • 939
  • 11
  • 22
0

In Swift 4:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    let firstVisibleIndexPath = self.tableview.indexPathsForVisibleRows?[0]
    print("top visible cell section  is \([firstVisibleIndexPath!.section])")
}
ib.
  • 27,830
  • 11
  • 80
  • 100
Radhe Yadav
  • 112
  • 11