如何知道UITableview行号

我有一个UITableViewCellUISwitch作为每个单元的附件。 当我改变单元格中的开关值时,怎样才能知道开关在哪一行? 我需要切换值更改事件中的行号。

标签,子类或视图层次结构导航功能太多了! 。 在你的行动方法中做到这一点:

 CGPoint hitPoint = [sender convertPoint:CGPointZero toView:self.tableView]; NSIndexPath *hitIndex = [self.tableView indexPathForRowAtPoint:hitPoint]; 

可以使用任何类型的视图,多节表格,只要发件人的原点在单元格框架内(感谢rob!),通常就是这样。

这里是在UITableView Swift扩展中:

 extension UITableView { func indexPath(for view: UIView) -> IndexPath? { let location = view.convert(CGPoint.zero, to: self) return self.indexPathForRow(at: location) } } 

如果将tag属性设置为行号(如其他答案所建议的那样),则必须在tableView:cellForRowAtIndexPath:每个单元格可以重复使用不同的行)中更新它。

相反,当你需要行号时,你可以从UISwitch (或任何其他视图)到UITableViewCell ,然后到UITableView ,并向表视图索引单元的索引路径。

 static NSIndexPath *indexPathForView(UIView *view) { while (view && ![view isKindOfClass:[UITableViewCell class]]) view = view.superview; if (!view) return nil; UITableViewCell *cell = (UITableViewCell *)view; while (view && ![view isKindOfClass:[UITableView class]]) view = view.superview; if (!view) return nil; UITableView *tableView = (UITableView *)view; return [tableView indexPathForCell:cell]; } 

这在tableView:cellForRowAtIndexPath:不需要任何东西。

cellForRowAtIndexPath: ,将控件的tag属性设置为indexPath.row

我更喜欢使用子视图,如果你知道你的布局,它通常是超级简单,1行短…

  NSIndexPath *indexPath = [tableView indexPathForCell:(UITableViewCell *)[[sender superview] superview]]; 

就是说,如果它嵌套更多,则会添加更多的高级视图。

位更多信息:

所有你正在做的是要求父视图和它的父视图这是单元格。 然后你问你的tableview你刚得到的那个单元格的indexpath。

接受的解决方案是一个聪明的黑客。

然而,为什么我们需要使用生命值,如果我们可以利用UIView上已经可用的tag属性? 你会说, 标签可以只存储行或部分,因为它是一个单一的Int

那么…不要忘记你的根源家伙(CS101)。 一个Int可以存储两个两倍大小的整数。 这是这个扩展:

 extension Int { public init(indexPath: IndexPath) { var marshalledInt: UInt32 = 0xffffffff let rowPiece = UInt16(indexPath.row) let sectionPiece = UInt16(indexPath.section) marshalledInt = marshalledInt & (UInt32(rowPiece) << 16) marshalledInt = marshalledInt + UInt32(sectionPiece) self.init(bitPattern: UInt(marshalledInt)) } var indexPathRepresentation: IndexPath { let section = self & 0x0000ffff let pattern: UInt32 = 0xffff0000 let row = (UInt32(self) & pattern) >> 16 return IndexPath(row: Int(row), section: Int(section)) } } 

在你的tableView(_:, cellForRowAt:)你可以:

 cell.yourSwitch.tag = Int(indexPath: indexPath) 

然后在动作处理程序中,您可以:

 func didToogle(sender: UISwitch){ print(sender.tag.indexPathRepresentation) } 

但是请注意这是限制: 行和部分不得大于65535. (UInt16.max)

我怀疑你的tableView的索引会走高,但如果他们这样做,挑战自己,实现更有效的包装方案。 假如我们有一个很小的部分,我们不需要全部16位代表一个部分。 我们可以有我们的int布局,如:

 {section area length}{all remaining}[4 BITS: section area length - 1] 

也就是说我们的4个LSB表示分区的长度 – 1,因为我们至少为一个分区分配了1个比特。 因此,如果我们的部分是0,那么这个行可以占用多达27位([1] [27] [4]),这肯定应该足够了。

一个常见的方法是将控件的tag (在你的情况下是开关)设置为可以用来标识行或表示对象的东西。

例如,在tableView:cellForRowAtIndexPath:将交换机的tag属性设置为indexPath.row并在您的操作方法中,您可以从发件人获取标签。

就个人而言,我不喜欢这种方法,更喜欢UITableViewCell的子类。 另外,向标签添加一个“偏移量”可能是一个好主意,以防止与其他视图的标签发生冲突。

一位同事建议如下,我把它做成了一个UITableView类:

 +(UITableViewCell*)findParentCellForSubview:(UIView*)view { while (([view isKindOfClass:[UITableViewCell class]] == NO) && ([view superview] != nil)) view = [view superview]; if ([view superview] != nil) return (UITableViewCell*)view; return nil; } 

仍然黑 – 但它的作品。

使用superView的更多变体。 像UIView类别工作。

 - (UITableViewCell *)superCell { if (!self.superview) { return nil; } if ([self.superview isKindOfClass:[UITableViewCell class]]) { return (UITableViewCell *)self.superview; } return [self.superview superCell]; } 

我不知道多个部分,但我可以给你一个部分…

 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSInteger index=indexPath.row; NSString *string=[[NSString alloc]initWithFormat:@"%ld",(long)index]; } 

从这里你可以得到行号,你可以把它保存到字符串….

这个帖子接受的答案是非常好的。 我想建议读者,在这篇文章中从@robmayoff派生的以下内容也完全正确:

 - (NSIndexPath *)indexPathForView:(UIView *)view inTableView:(UITableView *)tableView { while (view && ![view isKindOfClass:[UITableViewCell class]]) view = view.superview; UITableViewCell *cell = (UITableViewCell *)view; return [tableView indexPathForCell:cell]; } 

有些人认为这种方法由于while循环而包含了太多的计算工作。 另一种方法是将视图的原点转换为表视图坐标空间并调用indexPathForRowAtPoint:隐藏更多的工作。

有些人认为,这种方法相对于潜在的SDK更改是不安全的。 事实上,苹果公司已经改变了一次tableview单元格层次,添加一个contentView到单元格。 这种方法在这种变化之前和之后都有效。 只要查看祖先可以通过一系列的超级查看(这与UIKit中的任何东西一样重要),这是很好的代码。