如何从单元格获取UITableViewCell indexPath?


75

我如何从一个单元格中获取indexPath一个UITableView

我已经搜索了堆栈溢出和谷歌,但是所有的信息都是相反的。有什么方法可以访问superView/ UITableView,然后搜索单元格?

有关上下文的更多信息:我有两个类,一个被称为Cue,一个被称为CueTableCell(是的子类UITableViewCellCueTableCell是可视化表示Cue(这两个类彼此具有指针)。Cue对象位于链接列表中,并且当用户执行特定命令时,需要选择CueTableCell下一个的可视表示形式Cue。因此Cue类调用select的下一个方法Cue列表,以检索UITableViewcell并调用它selectRowAtIndexPath:animated:scrollPosition:,为它需要indexPathUITableViewCell


2
就像您从单元格获取问题一样UITableView为什么?这似乎是一个错误的设计决策的代码味道-单元格知道它的indexPath或是否在屏幕上没有多少合法的用例。
Paul.s 2013年

我同意Paul.s的评论。您应该指出为什么要这样做,因为您尝试执行的操作可能不是一个好主意。
rdelmar

@ Paul.s我在问题中张贴了程序的设计。这可能是不好的编程习惯,在这种情况下,如果您可以提出替代方案,那将非常有帮助。我对可可非常陌生,而对编程而言则相对较新。
SINθ

值得注意的是存在indexPathsForVisibleRows-当您想知道滚动条中的“您在哪里”时,这一点至关重要。
Fattie

Answers:


137
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];

即使有人认为这是有争议的,它也有助于阅读UITableView文档(请参阅下面的评论)。

该单元不知道其索引路径是什么。该控制器应该包含任何代码,基于所述数据模型或基于UI交互修改数据操纵UI元素。(请参阅MVC。)


41
如果您阅读了该问题,将会有所帮助。这是从没有TableView属性的UITableViewCell发出的(并且从所有角度来看,都不应如此)。
voidref

14
@voidref它还有助于思考问题;-)。该单元不知道其索引路径是什么。因此,此代码应在控制器中。有关MVC的背景信息,请参见Cocoa核心能力
Mundi 2013年

2
从一开始就可以明显看出该人需要正确的答案。
jdog 2014年

11
不回答原始问题。有时候,一个单元需要知道它的路径。例如,如果您对子类化单元实施了某种形式的滑动操作,则可能需要通知父视图当前正在滑动哪个单元。一种方法是让parentView中的方法遍历tableView单元并检查已在该单元中设置的iVar。更好的方法是使单元格通过委托方法通知父视图其indexPath ...因此单元格需要知道其indexPath。所以,蒙迪,最好回答这个问题,然后提出你的观点。
wuf810'4

4
索引路径是单元格和数据模型之间的“胶水”,因此它属于控制器。上面的一长串评论实际上是错误的。@ wuf810 ...因为控制器知道单元格和索引路径之间的关系,所以该单元格不(也不应该)。
Mundi 2014年

24

从您的UITableViewCell尝试以下操作:

NSIndexPath *indexPath = [(UITableView *)self.superview indexPathForCell: self];

编辑:似乎这在iOS 8.1.2及更高版本上不起作用。感谢克里斯·普林斯指出。


7
在iOS 8.1.2中,表视图单元的超级视图的类型为UITableViewWrapperView。该视图的类型为表视图。但是我认为我们在这里处于危险境地……
克里斯·普林斯

2
这一切都可以追溯到“该单元不知道其索引路径是什么”。论据。访问superview几乎总是一个hack,而且一段时间后不起作用也就不足为奇了。
fatuhoku

完全正确的fatuhoku,知道索引路径不是单元问题
Yahya Alshaar

11

您可以尝试以下简单技巧:

在您的UITableViewCell班级上:

@property NSInteger myCellIndex; //or add directly your indexPath 

和你的cellForRowAtIndexPath方法:

...
[cell setMyCellIndex : indexPath.row]

现在,您可以在任何地方检索单元格索引


5
您需要记住在重新排序或删除单元格后手动更新此信息。
康拉德

10

为了解决那些说“这是个坏主意”的人的需求,我的需要是我的按钮上有一个按钮UITableViewCell,当按下该按钮时,这是另一个视图的主题。由于这不是单元格本身的选择,[self.tableView indexPathForSelectedRow]因此不起作用。

这给了我两个选择:

  1. 将需要传递给视图的对象存储在表单元格本身中。虽然这工作,它会破坏我的点有一个NSFetchedResultsController,因为我没有做想所有对象存储在内存中,特别是如果该表是长。
  2. 使用索引路径从获取控制器中检索项目。是的,我不得不NSIndexPath通过黑客来找出问题,这似乎很丑陋,但最终比将对象存储在内存中要便宜。

indexPathForCell:是正确使用的方法,但是这就是我的操作方法(假定此代码在的子类中实现UITableViewCell

// uses the indexPathForCell to return the indexPath for itself
- (NSIndexPath *)getIndexPath {
    return [[self getTableView] indexPathForCell:self];
}

// retrieve the table view from self   
- (UITableView *)getTableView {
    // get the superview of this class, note the camel-case V to differentiate
    // from the class' superview property.
    UIView *superView = self.superview;

    /*
      check to see that *superView != nil* (if it is then we've walked up the
      entire chain of views without finding a UITableView object) and whether
      the superView is a UITableView.
    */
    while (superView && ![superView isKindOfClass:[UITableView class]]) {
        superView = superView.superview;
    }

    // if superView != nil, then it means we found the UITableView that contains
    // the cell.
    if (superView) {
        // cast the object and return
        return (UITableView *)superView;
    }

    // we did not find any UITableView
    return nil;
}

PS我的真实代码确实可以从表视图访问所有这些内容,但是我举了一个为什么有人可能想要直接在表单元格中执行类似操作的示例。


10
  1. 在单元格的.h文件中放置一个弱的tableView属性,例如:

    @property (weak,nonatomic)UITableView *tableView;

  2. 在cellForRowAtIndex方法中分配属性,例如:

    cell.tableView = tableView;

  3. 现在,无论您何时需要单元格的indexPath:

    NSIndexPath *indexPath = [cell.tableView indexPathForCell:cell];


之所以可行,是因为我们仅存储指向tableView本身的指针,但是indexPathForCell是否可靠?我以为这只提供可见单元格的indexPath吗?
jcpennypincher


4

这个问题的答案实际上对我有很大帮助。

我用了 NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];

sender在我的情况是UITableViewCell和来自prepareForSegue法。

我用这个,因为我根本TableViewController,但我有UITableView property outlet

我需要找出的标题,Cell因此需要知道它的indexPath。

希望这对任何人有帮助!


4

在iOS 11.0上,您可以使用UITableView.indexPathForRow(at point: CGPoint) -> IndexPath?

if let indexPath = tableView.indexPathForRow(at: cell.center) {
    tableView.selectRow
    (at: indexPath, animated: true, scrollPosition: .middle)
}

它获取单元格的中心点,然后tableView返回与该点相对应的indexPath。


1

尝试一下(仅当tableView只有一个部分并且所有单元格都具有相同的高度时才有效):

//get current cell rectangle relative to its superview
CGRect r = [self convertRect:self.frame toView:self.superview];

//get cell index
int index = r.origin.y / r.size.height;

0

从您的UITableViewCell尝试以下操作:

NSIndexPath *indexPath = [(UITableView *)self.superview.superview indexPathForCell:self];

-1

斯威夫特4.x

为了提供对我的单元的访问权限,我做了如下操作:

我有UIView的扩展:

extension UIView {
    var parentViewController: UIViewController? {
        var parentResponder: UIResponder? = self
        while parentResponder != nil {
            parentResponder = parentResponder!.next
            if let viewController = parentResponder as? UIViewController {
                return viewController
            }
        }
        return nil
    }
}

然后..在我的单元格类中:

class SomeCell: UITableViewCell {

    func someMethod() {
        if let myViewController = self.parentViewController as? CarteleraTableViewController {
            let indexPath : IndexPath = (myViewController.tableView).indexPath(for: self)!
            print(indexPath)
        }
    }
}

那就是我的全部。

最好的祝福。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.