自iOS7以来,indexPathForCell返回nil

19

我的应用在 iOS 6.1 上运行良好。我尝试了 iOS 7 模拟器,以下部分不起作用:

EditingCell *cell = (EditingCell*) [[textField superview] superview];
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
NSLog(@"the section is %d and row is %d", indexPath.section, indexPath.row);
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *rowKey = [[keysForRows objectAtIndex: section] objectAtIndex: row];

它总是到来:

the section is 0 and row is 0
尽管选择了另一部分/行,但为什么在iOS7下无法正常工作?

你是否验证了textfield.superview.superview是否为EditingCell类?单元格的视图层次可能已经发生了变化。 - Mick MacCallum
3
[[textField superview] superview]是引用任何内容的一种相当糟糕的方式。 - Desdenova
1
我已经拥有了这个应用程序,现在想让它在iOS 7下运行。 - Ludwig Meier
要查找单元格所属的类,请尝试 NSLog(@"Class of Cell: %@", NSStringFromClass(cell.class)); 还可以研究一下UITableView的方法“indexPathOfSelectedCell”。希望能有所帮助。 - katzenhut
单元格的类:UITableViewCellScrollView - Ludwig Meier
显示剩余7条评论
3个回答

30

你寻找文本字段的“包含”表视图单元格的方法很不稳定,因为它假设了一个固定的视图层次结构(似乎在iOS 6和iOS 7之间发生了变化)。

一种可能的解决方案是在视图层次结构中向上遍历,直到找到表视图单元格:

UIView *view = textField;
while (view != nil && ![view isKindOfClass:[UITableViewCell class]]) {
    view = [view superview];
}
EditingCell *cell = (EditingCell *)view;

一种完全不同但经常使用的方法是对文本字段进行“标记”,并附上行号:

cell.textField.tag = indexPath.row;   // in cellForRowAtIndexPath

然后只需在文本字段委托方法中使用该标签。


不错,这个方案可行(第一个解决方案)。还有什么需要注意的吗?或者这是正常的(或者一种正常的)方式吗? - Ludwig Meier
4
有一种情况使用标签可能无法起作用。如果您的代码在表格视图上执行了-insertRowsAtIndexPaths操作,那么标签将无法与indexPath.row匹配。 - Paul Heller
@PaulHeller:它应该匹配所有可见单元格,因为它始终在cellForRowAtIndexPath中更新,但是你是对的,你的反对意见同样使标记方法看起来脆弱。 - Martin R
如果行滚动出视图,父视图可能会返回nil并使您陷入无限循环。 - Bradley Thomas
@BradThomas:我曾经认为单元格内部控件的委托/动作方法中该单元格应该是可见的。但你永远不知道,因此添加一个检查 nil superview 的操作肯定是必须的(已添加到答案中)。感谢您的反馈! - Martin R
@MartinR,不客气。在我的情况下,我发现这个问题出现在textFieldDidEndEditing中,顺便说一句,当包含的单元格已被释放(例如不可见)时,在iOS6和iOS7中处理方式似乎有所不同。在我的情况下,我发现虽然iOS6对于NIB中未指定单元格重用标识符的情况宽容一些,但iOS7则不太一样。我的结论是,如果代码存在设计缺陷,则有可能出现其中一个包含视图为空的情况。我不太清楚是否可能在设计良好的代码中出现这种情况。 - Bradley Thomas

22

我以前也是像你一样查找单元格。现在,如果我有一个按钮在单元格内并且知道我所在的tableview,我会使用这种快速方法。它将返回tableviewcell。

现在我用这种快速方法查找单元格,只需要知道单元格里是否有按钮,并且知道当前的tableview。这样可以直接返回相应的tableviewcell。

-(UITableViewCell*)GetCellFromTableView:(UITableView*)tableView Sender:(id)sender {
    CGPoint pos = [sender convertPoint:CGPointZero toView:tableView];
    NSIndexPath *indexPath = [tableView indexPathForRowAtPoint:pos];
    return [tableView cellForRowAtIndexPath:indexPath];
}

3
这肯定是答案。越少依赖视图层级,就越好。 - Rizon
当indexPathForCell由于任何原因返回nil时,它能够很好地工作。在iOS 8上验证过。 - tedyyu

0
在iOS 11中遇到了这个问题,但在9或10中没有。我使用@drexel-sharp之前详细介绍的技术重写了func indexPath(for cell: UITableViewCell) -> IndexPath?方法。
override func indexPath(for cell: UITableViewCell) -> IndexPath? {
    var indexPath = super.indexPath(for: cell)
    if indexPath == nil { // TODO: iOS 11 Bug?
        let point = cell.convert(CGPoint.zero, to: self)
        indexPath = indexPathForRow(at: point)
    }
    return indexPath
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接