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