Given a UITableView, how can I find the location of a specific UITableViewCell? In other words, I want to get its frame relative to my iPhone screen, not relative to the UITableView. So if my UITableView is scrolled up, the location of each UITableViewCell should be higher on the screen, etc.
9 Answers
You could also use the rectForRowAtIndexPath method to get the location of a UITableView by sending the indexPath for that.
- (CGRect)rectForRowAtIndexPath:(NSIndexPath *)indexPath
So use as below:
CGRect myRect = [tableView rectForRowAtIndexPath:indexPath];
- 31,697
 - 9
 - 72
 - 76
 
- 
                    In which function are you accessing the `rectForRowAtIndexPath` method ? – Jhaliya - Praveen Sharma Jun 08 '11 at 14:40
 - 
                    1in the didSelectRow... method – CodeGuy Jun 08 '11 at 15:01
 - 
                    @reising1: It must not be crashed,if you still have the same issue you could show the related code . – Jhaliya - Praveen Sharma Jun 08 '11 at 16:20
 
Apart from rectForRowAtIndexPath you need to consider the scrolling.
Try this code:
 // Get the cell rect and adjust it to consider scroll offset
 CGRect cellRect = [tableView rectForRowAtIndexPath:indexPath];
 cellRect = CGRectOffset(cellRect, -tableView.contentOffset.x, -tableView.contentOffset.y);
- 
                    1
 - 
                    1+1 for taking into consideration the content offset. This will map the cell to its screen coordinates instead. nice one thanks. – Pavan Feb 20 '13 at 08:28
 - 
                    2The second line can be made simpler: `cellRect = CGRectOffset(cellRect, -tableView.contentOffset.x, -tableView.contentOffset.y);` – Tore Olsen Apr 18 '13 at 12:23
 - 
                    2You may also want to subtract the tableview's contentInsets if you have any `(-tableView.contentOffset.y-tableView.contentInset.top)` – Rob Caraway Feb 11 '14 at 14:20
 - 
                    2`rectForRowAtIndex` will return the rect in the UITableView's coordinate system. Use the `convertRect` method as described here http://stackoverflow.com/questions/687793/determine-coordinates-of-a-uitableviewcell-while-scrolling to convert it to the super view's coordinate system instead of fiddling with the offsets and insets manually. – Kalle Feb 17 '16 at 07:57
 
Try the following(sending nil as a toView parameter means you want to convert you rect to window coordinates):
CGRect r = [cell convertRect:cell.frame toView:nil];
And remember that if particular row is not currently visible then there may not be UITableViewCell for it - so before using that code you may need to check if cell is valid (not nil for example)
- 170,431
 - 36
 - 387
 - 313
 
- 
                    this is throwing an error. the program terminates. and yes, the cell is visible. – CodeGuy Jun 08 '11 at 14:34
 - 
                    
 
Swift 3
Relative to the tableView:
let rect = self.tableView.rectForRow(at: indexPath)
Relative to the Screen:
If you only know the cell,
if let indexPath = tableView.indexPath(for: cell) {
     let rect = self.tableView.rectForRow(at: indexPath)
     let rectInScreen = self.tableView.convert(rect, to: tableView.superview)
}
If you know the indexPath then don't need call the if statement.
- 15,423
 - 11
 - 100
 - 121
 
try it in
didSelectRowAtIndexPath method
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
        // get current location of selected cell
        CGRect rectInTableView = [tableView rectForRowAtIndexPath:indexPath];
        CGRect rectInSuperview = [tableView convertRect:rectInTableView toView:[tableView superview]];
         NSLog(@"Cell Y Is %f",rectInSuperview.origin.y);
        NSLog(@"Cell X Is %f",rectInSuperview.origin.x);
- 6,366
 - 15
 - 42
 - 50
 
- 321
 - 3
 - 7
 
Jhaliya's answer wasn't quite enough for me, I needed to do some more manipulations to get it working. My tableView was added to a viewController and its location on the right half way down the screen. So you need to take the tableView origin into account aswel as the scroll offset.
CGRect rowRect = [tableView rectForRowAtIndexPath:indexPath];
CGPoint offsetPoint = [self.infoTableView contentOffset];
// remove the offset from the rowRect
rowRect.origin.y -= offsetPoint.y;
// Move to the actual position of the tableView
rowRect.origin.x += self.infoTableView.frame.origin.x;
rowRect.origin.y += self.infoTableView.frame.origin.y;
- 559
 - 5
 - 13
 
For future viewers, I was having trouble getting a reliable frame for cells in a UITableView. I was trying to display a UIAlertController in ActionSheet style on an iPad which needs a popover presentation. In the end this approach yielded the best results:
// 44 is the standard height for a cell in a UITableView
// path is the index path of the relevant row
// controller is the UIAlertController
CGRect frame = CGRectZero;
frame.origin.y = 44 * path.row;
frame.origin.x = table.frame.origin.x;
frame.size = CGSizeMake(table.frame.size.width, 44);
controller.popoverPresentationController.sourceRect = [tableView convertRect:frame toView:self.view];
controller.popoverPresentationController.sourceView = self.view;
- 5,197
 - 3
 - 31
 - 58
 
- 
                    I ended up using your answer. Instead of hard coding it to 44 you should use cellForRowAtIndexPath and then use the bounds.height of the cell. – John Jun 11 '16 at 18:03
 
Swift-version of Tomasz and Jhaliya's answers in case anyone (else) struggles with this:
var cellRect = tableView.rectForRow(at: indexPath)
cellRect = cellRect.offsetBy(dx: -tableView.contentOffset.x, dy: -tableView.contentOffset.y)
- 6,373
 - 4
 - 22
 - 32
 
If you really need to convert specifically to a point in the window, you could do this:
[yourAppDelegate.window convertPoint:[cell.contentView.center] fromView:[cell.contentView]];
I used the cells center coordinate, but you could use any point you want.
Vladimir is right, watch out for rows that are not visible (or that have been recycled).
-S
- 2,667
 - 3
 - 30
 - 37